パス内のすべてのディレクトリとファイルを再帰的に検索したいが、特定のパターンに一致する他のいくつかのディレクトリとファイルを除外したい。次に、検索結果に対してさらにコマンドを実行したいと思います。たとえば、cp
、mv
、rsync
、またはrm
find
の結果です。
node_modules
、.git
、build
ディレクトリ全体、およびenhancers
ディレクトリ全体をプルーニングしたいが、検索結果に-namexyz.js
のファイルを含めたいとします。 enhancers
ディレクトリ。
以下のコマンドを使用すると、検索結果にxyz.js
ファイルを含めることを除いて、目的の結果を得ることができます。コマンドは非常に長いです。
find . -path "./node_modules" -Prune -o -path "./.git*" -Prune -o -path "./build" -Prune -o -path "*/enhancers" -Prune -o -print | grep 'xyz.js'
--root
|--node_modules
|--public
|--build
|--.git
|--.gitignore
|--.env
|--package.json
|--src
|--history
|--store
|--middleware
|..
|..
|--enhancers
|..
|--xyz.js
上記の概略ディレクトリ構造では、|..
はディレクトリ内の不明な深さ(レベル)を表します。
示されているディレクトリ構造で、以下を除くすべてのファイルを検索結果に含めたい
node_modules
ディレクトリ全体.git
ディレクトリ全体.gitignore
ファイルenhancers
ディレクトリ全体ですが、検索結果にxyz.js
ファイルを含めますそれを行うためのより短い方法はありますか?主な混乱は、正規表現とグロブのパターンの間です。
./.git*
を./\.git*
に置き換えると、それも機能します。
*
で複数の*/enhancers
を使用する場合も、機能します。
find
コマンドで適用できるファイルとディレクトリの検索パターンルールは何ですか?
enhancers
内のファイルを見つけたい場合は、Prune
できません。 Prune
は、find
がまったく下降しないことを意味するため、そこにファイルが見つかる可能性はありません。ここでは、それらをプルーニングするのではなく、それらの下にあるxyz.js
ファイル以外のファイルを除外する必要があります。
そう:
find . \( \
-path ./node_modules -o \
-path './.git*' -o \
-path ./build \
\) -Prune -o \( \
! -path '*/enhancers' ! -path '*/enhancers/*' -o \
-name xyz.js \
\) -print
ここでは読みやすさのためにいくつかの行にあります。
これらのファイルで何かをしたい場合は、-print
を-exec sh -c 'for file do something with "$file"; done' sh {} +
に置き換えてください。
または、出力を後処理する場合は、-print0
を使用し、grep
/xargs
/cut
/sort
の-z
/--null
/-0
オプションを使用します。 (GNU実装または互換性があると仮定))NULで区切られた入力で動作します。
フィルタルールを使用して2つのrsync
コマンドラインでbashシェルスクリプトを作成できます。
#!/bin/bash
rsync -Havn \
--filter="- target" \
--filter="- node_modules" \
--filter="- .git" \
--filter="- build" \
--filter="- enhancers" \
./ target
rsync -Havn \
--filter="+ xyz.js" \
--filter="+ */" \
--filter="- *" \
src target
-n
でNice出力が生成されるまで、このシェルスクリプトを編集するのはかなり簡単です。これは、「ドライラン」が意図を示すだけであることを意味します。
問題がなければ、2つのコマンドラインから-n
を削除して、rsync
に処理を任せることができます。あるいは、テキスト出力に満足していて、それをファイルに保存するか、何らかの方法で他のコマンドにパイプする(rsyncコピー以外のことを行うため)かもしれません。