このユースケースで grep と cp を使用して適切にパイプ検索を行う方法

このユースケースで grep と cp を使用して適切にパイプ検索を行う方法

ディレクトリ内の文字列をパターンに従って再帰的に grep し、一致するファイルを宛先ディレクトリに cp することに興味があります。次のようなことができると思いましたが、Linux の find ツールでは意味がないようです。

find . -type f -exec grep -ilR "MY PATTERN" | xargs cp /dest/dir

これを実行するより良い方法はあるでしょうか? あるいは、うまくいく方法があれば、確実なスタートとなるでしょう。

答え1

man xargs旗を見てやりましょう-I

find . -type f -exec grep -ilR "MY PATTERN" {} \; | xargs -I % cp % /dest/dir/

また、フラグの後にまたは が続くfindことを期待します。\;+-exec

答え2

find は必要ないと思います。再帰 grep:

grep -rl "MY PATTERN" .

答え3

xargs標準入力を読み取り、実行するコマンドの末尾に置きます。あなたが書いたように、最終的に実行することになります。

cp /dest/dir sourcefile1 sourcefile2 sourcefile3

それはあなたが望むものとは逆です。

オプションを使用して、次のよう-Iに のプレースホルダーを指定できます。xargsxargs -I '{}' cp '{}' /dest/dir

また、findは再帰を処理するので、 はgrep必要ありません-R

最終的解決:

find . -type f -exec grep -il "MY PATTERN" '{}' + | xargs -I '{}' cp '{}' /dest/dir

答え4

上記の例ではいずれも、grep-l重複した結果 (同じ名前だが場所が異なるファイル) を生成する可能性を考慮していません。そのため、 のフックによって宛先ディレクトリ内のファイルが上書きさfindれますexec

これを解決するための試み:

$ tree foo
foo
├── bar
│   ├── baz
│   │   └── file
│   └── file
├── destdir
└── file

3 directories, 3 files

$ while read a; do mv $a foo/destdir/$(basename $a).$RANDOM; done < <(grep -rl content foo)

$ tree foo
foo
├── bar
│   └── baz
└── destdir
    ├── file.10171
    ├── file.10842
    └── file.25404

3 directories, 3 files

関連情報