
私は現在のディレクトリの下のすべてのディレクトリとファイルを一覧表示し、次を使用してファイルかディレクトリであるかを書きたいと思います。
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
まず、コードスニペットがコマンドを実行します。
echo {} : ;if [ -f {} ]; then echo file; else echo directory;fi
コマンド置換を評価するには出力が必要なためです。というファイルがないため、{}
出力が生成されます。
{} :
directory
find
その後、コマンドは-exec
、、、およびパラメータを使用して実行されるため、各ファイルのファイル名の後にスペースとが表示されますecho
。{}
:
directory
: directory
echo {} :; …
実際に望むのは、で見つかったすべてのファイルに対してシェルフラグメントを実行することですfind
。このコードスニペットはコマンドラインからデータを受け取るため、開始されたシェルではfind
なく作成されたシェルで実行する必要があります。したがって、実行中のシェルに次のように指示する必要があります。find
find
find
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' _ {} +
答え2
if; then; else; fi
これを行うもう1つの方法は次のとおりですfind
。
find |
while IFS= read -r p; do if [ -f "$p" ]; then echo file; else echo directory; fi; done