ファイル内の単語をGrepしてからファイルをコピーする


9

ファイルのコレクションがあります(* .zip、*。txt、*。tar.gz、*。doc、... etc)。これらのファイルはパス内にあります。すべてのファイル(* .txt)を検索し、特定の単語を含むテキストファイル(たとえば、LINUX / UNIX)のみをコピーしたい。

私は以下を実行しました:

find . -name "*.txt" | grep 'LINUX/UNIX'

このコマンドはすべてのテキストファイルを見つけることができ、 "grep"は 'LINUX / UNIX'を含むテキストファイルのみを一覧表示することにより、結果のテキストファイルをフィルター処理しました。

これらの最終的なファイル(つまり、 'LINUX / UNIX'を含むテキストファイル)を特定の選択したパスにコピーするにはどうすればよいですか?

応募してみました xargs

find . -name "*.txt" | grep 'LINUX/UNIX' | xargs cp <to a path>

しかし、それはうまくいきませんでした


回答:


21

試してください:

grep -rl --null --include '*.txt' LINUX/UNIX . | xargs -0r cp -t /path/to/dest

このコマンドはNUL区切りを使用するため、空白、タブ、または改行を含む難しい名前のファイルを含むすべてのファイル名で安全です。

上記にはGNUが必要cpです。MacOS / FreeBSDの場合:

grep -rl --null --include '*.txt' LINUX/UNIX . | xargs -0 sh -c 'cp "$@" /path/to/dest' sh

使い方:

  1. grep オプションと引数

    • -rディレクトリ構造全体を再帰的に検索するようにgrepに指示します。(FreeBSDでは、-rディレクトリへのシンボリックリンクをたどります。これは、OS / Xや最近のバージョンのGNUには当てはまりませんgrep。)

    • --include '*.txt'grepに、グロブに一致する名前のファイルのみを返すように指示します*.txt.foo.txtまたはのような隠しファイルも含む.txt)。

    • -l 一致自体ではなく、一致するファイルの名前のみを返すようにgrepに指示します。

    • --nullファイル名を区切るためにNUL文字を使用するようにgrepに指示します。(GNU / LinuxMacOSFreeBSDで--nullサポートさgrepれてますOpenBSD ではサポートされていません。)

    • LINUX/UNIX 内容が正規表現を含むファイルのみを探すようにgrepに指示します LINUX/UNIX

    • .現在のディレクトリを検索します。最近のバージョンのGNU grepでは省略できますが、で始まるファイル名を防ぐ--ためcpにオプションターミネータを渡す必要があります-

  2. xargs オプションと引数

    • -0 xargsにNUL区切りの入力を期待するように伝えます。

    • -r少なくとも1つのファイルが見つからない限り、コマンドを実行しないようにxargsに指示します。(このオプションはBSDとOSXのどちらにも必要なく、OSXと互換性がありませんxargs。)

    • cp -t /path/to/destディレクトリをターゲットディレクトリにコピーします。(-tGNUが必要cpです。)


Mac OS X、そしておそらくBSDの場合、-Zの代わりに--nullを使用する必要があります。また、cp -tLinux専用だと思います。
エドワードフォーク

1
@EdwardFalk良い点。ありがとう。を使用するように更新し--null、BSD / OSXを使用しないバージョンを追加しましたcp -t
John1024

@StéphaneChazelas改善に感謝します。
John1024

1
OpenBSDにgrepはありません--null
Kusalananda

@Kusalanandaありがとう。回答が更新され、OpenBSDはサポートしていません--null
John1024

14

より移植性の高い(POSIX機能のみ):

find . -type f -name '*.txt' -exec grep -q LINUX/UNIX {} \; -exec cp {} /path/to/dest \;

3

次のsh / Bashの1つのライナーは別の方法ですが、現在のディレクトリでのみ機能し、再帰しません。

for f in ./*.txt; do if grep -l 'LINUX/UNIX' "$f"; then cp "$f" /path/to/dest/; fi; done

-lgrep のオプションは、コピーされているファイルのリストを印刷しますが-q、画面に何も表示したくない場合に使用できます。


0

元の文字列が機能しなかった理由がわかりません。次のコマンドは私のために働きます。

検索/ -name(ファイル名*)| grep '(filename.extention)' | xargs cp -t ./

私の場合、filename *は同じ名前のファイルのコレクションで、異なるファイルタイプ(txt、zipなど)です。grepを実行して、filename.txtのみを見つけ、それを宛先ディレクトリー(現在は./)にコピーします。

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