find と他のコマンドを組み合わせる: -exec をいつ使用し、パイプをいつ使用するか?

find と他のコマンドを組み合わせる: -exec をいつ使用し、パイプをいつ使用するか?

ファイルやディレクトリを見つけるために find コマンドを単独で使用する方法を学習しましたが、ファイルやフォルダを使用して何かを行うとなると混乱してしまいます。

次のコマンドを実行します。

find . -type f -iname "*.cr2" 

cp上記のファイルを新しいディレクトリにコピーしたい場合は、当然 copy( ) と pipe を使用すると思います|

find . -type f -iname "*.cr2" | cp \destination_directory

そして私にとっては、これにより、ドライブ全体にわたるすべての写真がサブフォルダーの階層にネストされて 1 つのフォルダーにまとめられ、整理を始める準備が整います。

しかし、パラメータを使用するように言われ続けるので、私の質問は、以下のようにいつパイプを使用し、いつコマンドを使用するかを-execどのように判断するかということです。|-exec

 find . -name "*.pdf" -type f -exec cp {} ./pdfsfolder \;

編集

提案された解決策 (下記) は、ファイル名が一意であるファイルのみをコピーします。cp は file.txt をコピーせず、file.txt に置き換えます。多数のファイルをコピーし、同じ名前のファイルがあるかどうかわからない場合、ファイル名が存在する場合に何かをコピーして名前を変更するにはどうすればよいでしょうか。

提案された解決策

find . -type f -iname "*.txt" -print0 | xargs -0 cp -t /home/josh/Documents/copy/

/home/josh/documents/copy は、データを移動したいディレクトリです。

答え1

あなたの仮定には誤りがありますが、まず背景を説明します。

の 2 つの用途を認識する必要があります-exec

  • は、\;見つかっ{} た単一のアイテムに置き換えられます
  • は、+多く{}の項目 (コマンドラインに保持できる数だけ) に置き換えられます。

したがって、使用例では、 によって見つかった項目と-exec同じ数のコマンドが呼び出されます。cpfind

を使用するfind ... -exec cmd {} ... +と、find の出力を複数の入力名を処理するコマンドにパイプするのと効率が似ています。

-execまた、スペースを含むファイル名/パスを適切に処理しますが、find からの出力を別のプログラムにパイプすると問題が発生する可能性があることも考慮する必要があります。したがって、stdin からファイル名のリストを期待する一部のプログラムには、それらのファイル名を NUL で区切るオプション (多くの場合、または-0)--nullを指定できます。また、find次のように指定することで、次のプログラムにそのように渡すオプションがあります。-print0


さて、あなたの例を見てみましょう:

find . -type f -iname "*.cr2" | cp destination_directory

cp は標準入力から読み込まないため、見つかったファイルをコピーしません。次のように使用する必要があります。

find . -type f -iname "*.cr2" | xargs cp -t destination_directory

または、スペースを含むパスを処理するには:

find . -type f -iname "*.cr2" -print0 | xargs -0 cp -t destination_directory

ほぼ同じ効率で、次の操作を実行できます。

find . -type f -iname "*.cr2" -exec cp -t destination_directory {} +

(G-Manが指摘したように、 は{}の前の最後になければなりません+)上記のすべてはないそのためにターゲット ディレクトリの下に階層を構築し、長年の習慣により、ソース ディレクトリがフラットであっても、cpio代わりに以下を使用するようになりました。

find . -type f -iname "*.cr2" -print0 | cpio -pdmv0 destination_directory

途中で何を実行しているかをわかりやすくリストします。


関連部分man find:

-exec command ;
       Execute command; true if 0 status is returned.   All  following
       arguments  to  find  are  taken  to be arguments to the command
       until an argument consisting of `;' is encountered.  The string
       `{}'  is  replaced  by  the  current  file name being processed
       everywhere it occurs in the arguments to the command, not  just
       in  arguments  where  it is alone, as in some versions of find.
       Both of these constructions might need to be  escaped  (with  a
       `\')  or  quoted  to  protect them from expansion by the shell.
       See the EXAMPLES section for examples of the use of  the  -exec
       option.   The  specified  command  is run once for each matched
       file.  The command  is  executed  in  the  starting  directory.
       There  are unavoidable security problems surrounding use of the
       -exec action; you should use the -execdir option instead.

-exec command {} +
       This variant of the -exec action runs the specified command  on
       the  selected files, but the command line is built by appending
       each selected file name at the end; the total number of invoca‐
       tions  of  the  command  will  be  much less than the number of
       matched files.  The command line is built in much the same  way
       that xargs builds its command lines.  Only one instance of `{}'
       is allowed within the command.  The command is executed in  the
       starting directory.

関連情報