find -execのifコマンド


9

私は現在のディレクトリの下にあるすべてのディレクトリとファイルを一覧表示し、それらがファイルまたはディレクトリである場合は、次のコマンドで書き込もうとしました:

find -exec echo `echo {} : ;if [ -f {} ]; then echo file; else echo directory;fi` \;

私はそれがばかげたコマンドであることを知っています、-type fまたはのような他のものを使用できます-type dが、そのコードの一部が期待どおりに機能しなかった理由を知りたいです。それらすべてにディレクトリを出力するだけです。たとえば、出力findは次のとおりです。

.
./dir
./dir/file

私のコードの出力は:

. : directory
./dir : directory
./dir/file : directory

そしての出力

echo `echo dir/file : ;if [ -f dir/file ]; then echo file; else echo directory;fi`

です

dir/file : file

私が働いているUbuntu 14.10と使用しますfind (GNU findutils) 4.4.2


1
find -exec bash -c 'echo -n "{} : ";if [ -f "{}" ]; then echo file; else echo directory;fi' \;
コスタ2015

1
@Costasに感謝しますが、bashまたはshを使用して最初の目標を達成できることはわかっていますが、execパラメータで動作が異なる場合の理由を理解したいと思います。
Esref、2015

引数を引用符で囲みます"{}"。なぜecho二度使うの?
コスタ2015

私はすでにそれを試しました、そしてそれは同じ出力を与えます。find -exec echo echo "{}" : ;if [ -f "{}" ]; then echo file; else echo directory;fi\;
Esref、2015

回答:


13

まず、スニペットがコマンドを実行します

echo {} : ;if [ -f {} ]; then echo file; else echo directory;fi

コマンド置換を評価するには出力が必要だからです。という名前のファイルがないため{}、これにより出力が生成されます

{} :
directory

その後、findコマンド引数で実行され-exececho{}:directory、ので、すべてのファイルに対して、それは宇宙と続くファイル名を出力します: directory

実際に実行したいことは、echo {} :; …によって検出された各ファイルに対してシェルスニペットを実行することfindです。このスニペットは、コマンドラインからデータを受信して​​いるため、findを起動するシェルではなく、によって生成されたシェルによって実行される必要があります。したがって、シェルを実行するように指示する必要があります。findfindfind

find -exec sh -c 'echo {} : ;if [ -f {} ]; then echo file; else echo directory;fi' \;

これは良いですが、まだ正しくありません。findファイル名に特殊文字が含まれていない場合、一部(すべてではない)の実装で機能しますが、シェルスクリプトでファイル名を補間しているため、たとえば、呼び出されたファイル$(rm -rf /)は、コマンドrm -rf /が実行されます。ファイル名をスクリプトに渡すには、それらを個別の引数として渡します。

また、最初echoはコロンの後に改行を出力します。使用echo -n(あなたのシェルがそれをサポートしている場合)、またはprintfこれを回避します。

find -exec sh -c 'printf "%s :" "$0"; if [ -f "$0" ]; then echo file; else echo directory; fi' {} \;

-exec … {} +シェル呼び出しをグループ化するために使用できます。これはより高速です。

find -exec sh -c 'for x; do printf "%s :" "$x"; if [ -f "$x" ]; then echo file; else echo directory; fi; done' _ {} +

3

if; then; else; fi一緒に実行する別の方法findは次のとおりです。

find |
while read p; do if [ -f "$p" ]; then echo file; else echo directory; fi; done

1
クールなソリューション。複雑な引用パターンやサブシェルの複雑化を回避します。以前にシェル関数を定義し、「if」条件に一致するファイルでそれを実行した可能性があります。
gerlos、2018年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.