it-mure.jp.net

grep出力をscpにフィードする方法は?

各行がファイル名であるファイルがあります。ファイルの内容:

_file1
file2
file3
...
_

次に、grepコマンドを実行して、ファイル名のリストのサブセットを取得します。

grepコマンドの出力をscpにフィードするにはどうすればよいですか? xargs$()をいじってみましたがあまり成功しませんでした...

2
dognar

xargsを使用する必要はありません:

for file in $(grep <some-pattern> <filelist>); do scp $file <remote>; done;

どこ

  • <some-pattern>はあなたのgrepパターンです
  • <filelist>はファイルのリストです
  • <remote>は、scpコマンドのリモートエンドです。

forループは、grepによって生成された各行を繰り返し処理し、これを$fileに渡します。これは、dodoneの間で実行されるコマンドで再利用できます。

参照: 高度なBashスクリプトガイド:–ループ

3
slhck

1行に1つの名前でファイル名のリストを反復処理するには、いくつかの可能性があります。

  • コマンド置換を使用して、ファイルをシェル内のファイル名のリストに変換します。コマンド置換の結果を単語に分割する必要があるため、コマンド置換を二重引用符で囲むことはできないため、注意が必要です。グロブをオフにし、改行で単語を分割するようにIFSを設定する必要があります。

    set -f; IFS='
    '
    scp -- $(…) remote.example.com:
    
  • 組み込みのreadを使用して、ファイル名をループで処理します。繰り返しますが、readは円記号と$IFS文字を特別に扱うため、注意が必要です。

    … | while IFS= read -r x; do scp -- "$x" remote.example.com: done
    
  • GNU xargsを使用できますが、xargsは奇妙な引用形式での入力を想定しているため、慎重に検討する必要があります。入力として改行を明示的に選択するには、-d '\n'オプションを渡す必要があります。区切り文字を使用して、空白と\'"の特別な動作をオフにします。

    … | xargs -d '\n' -I {} scp {} remote.example.com:
    

    xargsの唯一の利点は、コマンドラインの長さの制限まで複数の引数を1つの呼び出しにグループ化できることですが、これは引数が最後にコマンドに渡された場合にのみ機能します。 shを中間的に呼び出すことでそれを実現できますが、問題を起こす価値はほとんどありません。

    … | xargs -d '\n' sh -c 'scp -- "[email protected]" "$0"' remote.example.com:
    
  • xargsを使用する簡単な方法は、改行で区切られたリストではなく、nullで区切られたリストを取得することです。これには-0オプションが必要です。これはGNU xargsおよび最近の* BSDでもサポートされています。上記のように、引数を非最終位置に押し込むには少し作業が必要です。

    … | tr '\n' '\0' | xargs -0 sh -c 'scp -- "[email protected]" "$0"' remote.example.com:
    

正規表現でファイル名をフィルタリングする場合、の部分はgrep NAME_REGEXP /path/to/filenames.listになります。ファイルの内容をフィルタリングする場合は、上記の手法のいずれかを使用して、ファイル名をgrepにフィードします。

set -f; IFS='
'
scp -- $(grep -l CONTENT_REGEXP -- $(cat /path/to/filenames.list)) \
    remote.example.com:

シェルの問題を回避するもう1つの可能性は、rsyncとその--files-fromオプションを使用することです。ファイル名がすべて現在のディレクトリに関連していると仮定します。

grep NAME_REGEXP /path/to/filenames.list |
rsync -a --files-from - . remote.example.com:

readを使用して、出力を1行ずつ解析します( https://stackoverflow.com/a/7039208 ); grep <some-pattern> <filelist> | while read file; do scp $file <remote>; done;

0
gamdow