node_modules
私はnode.jsフォルダの内容やPythonのvirtualenv
基本的な依存関係を調べるためのクイックツールを書いています。これを素早く最初の近似で次のコマンドを作成しました。
find . | xargs file | awk '/C source/ {print $1} /ELF/ {print $1}'
偽の肯定は許可されますが、偽の否定は許可されません(たとえば、ファイルに文字通り文字列が含まれているか、ELF
疑わしいとマークされる可能性があります)。ただし、このスクリプトは長いファイル名(分割されているため)とスペースを含むファイルC source
でも失敗する可能性があります。xargs
スペースに分割されます)と改行を含むファイル名(findがパスを区切るために改行を使用するため)。
find
出力file {}
(おそらく出力からパスを完全に削除するためにいくつかの追加オプションを使用file
)が特定の正規表現と一致することを確認して生成されたパスをフィルタリングする方法はありますか?
答え1
悟りを達成する重要な要素はfind
次のとおりです。
find
仕事はファイルを見つけるのではなく、式を評価することです。はい、find
もちろんファイルを見つけることができますが、実際には副作用だけです。
この問題には、もう1つのアプローチがあります(Unix Power Toolsにも説明されています)。"-execを使用したカスタムテストの作成"):
find . -type f -exec sh -c 'file -b "$1" | grep -iqE "^ELF|^C source"' sh {} \; -print
このフィルタリング方法は、ファイル名を印刷する以外の目的で使用できるため、知っておくことをお勧めします。-print
演算子を他の演算子を含む他の演算子-exec
に変更し、必要に応じて実行できます。
そこはいこのコマンドのパフォーマンス障害(次にも表示されます)もう一つの答え\;
)、私たちは使用していないので、+
各ファイルに対してシェルを生成します。一度に複数のファイルをコマンド+
に渡してループを使用して処理すると、パフォーマンスが大幅に向上します。sh
for
find . -exec sh -c 'for f do file -b "$f" | grep -qE "^ELF|^C source" && printf %s\\n "$f"; done' sh {} +
次の2つのコマンドを実行し、出力を比較して直接比較内容を確認できますtime
。
time find . -exec sh -c 'for f do file -b "$f" | grep -qE "^ELF|^C source" && printf %s\\n "$f"; done' sh {} +
time find . -exec sh -c 'file -b "$1" | grep -qE "^ELF|^C source" && printf %s\\n "$1"' sh {} \;
しかし、実際のポイントは次のとおりです。
for
から出力されるファイルのリストに対してシェルループを実行しないでくださいfind
。find
代わりに、演算子を使用して各ファイルで実行する必要があるタスクを直接実行できます-exec
。含めるシェルfor
ループ以内に1つのコマンドをfind
実行するだけです。
いくつかの追加理由:
答え2
最も簡単な方法は、各ファイルに対して小さなスクリプトを実行し、短いパターン出力を確認し、出力が一致したりパスを印刷したりすると、パスがfile
にfile
渡さELF
れるC source
ことです$0
。
find . -type f -exec sh -c \
'file -b "$0" | grep -q "^ELF\|^C source" && printf %s\\n "$0"' {} \;
この計画は、元の計画と比較して次の利点があります。
-type f
出力に依存するのではなく、すぐにディレクトリをフィルタリングします。file
パラメータを渡すと、{}
ファイル名のスペースや改行に関連する問題を回避できます。