grep
1TBのファイルを検索するために使用しています。ファイル名をgrepし、名前をテキストファイルに入れたいので、cp
dirと一致するすべてのファイルが欲しいです/home/user/matches
。すべてのファイルを2回grepingせずに両方の操作を実行したいと思います。
私の考えは、grepを使用してファイル名の出力をテキストファイルに入れることです。
grep -ril "xxx" . >> /home/user/matches/output-filename.txt
これでoutput-filename.txt
cpへの入力として機能し、cpが1行ずつ実行されるようにします。どうすればいいですか?え?それとも、すべてのファイルを2回検索しないようにする他のアイデアはありますか?
答え1
ファイルパスはゼロ以外のバイトシーケンスです。テキスト行はもちろん、テキストである必要はありません。特にファイルパス
- 改行文字を含めることができます。
- 有効な文字を形成しないバイトシーケンスを含めることができます。
- LINE_MAXより長い場合があります。
GNU実装grep
(オプションを追加した実装-r
)はテキスト以外の形式でパスを印刷でき、-Z
後処理に安全です。たとえば、GNUはxargs
オプションを使用してこの形式を処理できます-0
。
xargs -r0 -a <(
grep -rilZ xxx . |
tee file.list
) cp -it /home/user/matches --
(これもGNUをオプションcp
と仮定します-t
)
GNUを使用して人が読めるテキスト形式でリストを印刷するには、次の手順を実行しますprintf
。
xargs -r0a file.list printf '%q\n'
1文字が表現としてレンダリングされるため、デコードできないバイトを保証する必要があります$'\234'
。$'\n'
サポートLINE_MAX
する行数に制限はありません)。
答え2
find
一対の接続コマンドを使用できますexec
。grep
すべてのファイル(および一致するすべてのファイル)に対して呼び出されるため、最も効率的な解決策ではないかもしれませんが、cp
ファイル名の文字に関係なく機能します。
mkdir -p ~/matches
find -type f -exec grep -il 'xxx' {} \; -exec cp -p {} ~/matches/ \; > ~/matches/output-filename.txt