ディレクトリ内の文字列をパターンに従って再帰的に 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
に のプレースホルダーを指定できます。xargs
xargs -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