web-dev-qa-db-ja.com

このユースケースでgrepおよびcpを使用してfindを適切にパイプ処理する方法

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

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

これについてより良い方法はありますか?あるいは、うまくいく方法でもしっかりしたスタートです。

3
imaginative

man xargsを実行し、-Iフラグを確認します。

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

また、findでは、\;フラグの後に+または-execが必要です。

12
Sammitch

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
1
200_success

あなたが見つける必要はないと思います。再帰的なgrep:

grep -rl "MY PATTERN" .
1
Neil H Watson

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

これを解決する試み:

$ 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
1
dawud