grepの出力をscpに送るにはどうすればいいですか?


1

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

file1
file2
file3
...

それから私は走ります grep ファイル名のリストのサブセットを取得するコマンド。

どのように私はの出力を供給するのですか grep コマンドイン scp?私は遊んだことがある xargs そして $() あまり成功せずに…

回答:


2

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

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

どこで

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

for ループは、によって生成された各行を反復します。 grep そしてこれをに渡す $file間で実行されたコマンドで再利用できます。 do そして done

また見なさい: 上級Bashスクリプトガイド: - ループ


1
(スペースの場合)あなたのファイル名を引用するのを忘れないでください。
SamK

1
ファイル名のいずれかに空白文字またはグロブ文字が含まれていると、これは機能しません。
Gilles

今検索するファイルが何千もあるとします。効率的な方法は何ですか?
StatsSorceress

@StatsSorceressより速い grep ファイルをpingしますか?今は何も考えられませんが、Gillesの答えはいずれにしても優れています。
slhck

1

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 -- "$@" "$0"' remote.example.com:
    
  • より簡単な使い方 xargs 改行ではなくNULLで区切られたリストを取得することです。これには -0 これはGNU xargsと最近の*​​ BSDでサポートされています。上記のように、引数を最終的でない位置に押し込むには、少し作業が必要です。

    … | tr '\n' '\0' | xargs -0 sh -c 'scp -- "$@" "$0"' remote.example.com:
    

一部は grep NAME_REGEXP /path/to/filenames.list 正規表現を使ってファイル名をフィルタリングするつもりなら。ファイルの内容をフィルタリングするつもりなら、上記のテクニックの1つを使ってファイル名を 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:

とても手の込んだ、私はあなたにそれをあげる! (ただ疑問に思っているが、それがOPのために働いたのであれば、それはまだ下投票を正当化するのか?)
slhck

@slhck間違っている答え(そして、私がちょうどあなたの答えを編集したことがあるのであれば、私は詳細を言うのを間違っているわけではありません)は正当な下方投票の目標です。 すべき 軽蔑される。簡単な例でテストしたときに正しいように見えますが、現実のシナリオではうまくいかない答えが最悪です。
Gilles

まあ、それがうまくいくとき、それは「間違って」いません - たとえそれが単純なシナリオであるとしても。ボタンは実際には「この答えは役に立たない」と言っています、そしてそれは明らかに だった 有用。私はそれが複雑なファイル名を扱うつもりではないことを知っていました、そして上記のあなたのコメントを加えることによって、それは絶対に明らかにされました。しかし、ええ、それをそのままにしましょう、それを争うつもりはありません!
slhck

あなたの詳細な答え、Gillesに感謝します。複雑なファイル名に出会えば便利だと思います。
dognar

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.