findコマンドを使用しますが、2つのディレクトリ内のファイルを除外します


86

で終わるファイルを見つけたいの_peaks.bedですが、フォルダー内のファイルを除外tmpscriptsます。

私のコマンドは次のようなものです:

 find . -type f \( -name "*_peaks.bed" ! -name "*tmp*" ! -name "*scripts*" \)

しかし、それはうまくいきませんでした。tmpおよびscriptフォルダ内のファイルは引き続き表示されます。

誰かがこれについてアイデアを持っていますか?

回答:


189

これを次のように指定する方法は次のfindとおりです。

find . -type f -name "*_peaks.bed" ! -path "./tmp/*" ! -path "./scripts/*"

説明:

  • find . -現在の作業ディレクトリから検索を開始します(デフォルトでは再帰的に)
  • -type f-find結果にファイルのみが必要であることを指定します
  • -name "*_peaks.bed" -名前がで終わるファイルを探します _peaks.bed
  • ! -path "./tmp/*" -パスがで始まるすべての結果を除外します ./tmp/
  • ! -path "./scripts/*" -パスがで始まるすべての結果も除外します ./scripts/

ソリューションのテスト:

$ mkdir a b c d e
$ touch a/1 b/2 c/3 d/4 e/5 e/a e/b
$ find . -type f ! -path "./a/*" ! -path "./b/*"

./d/4
./c/3
./e/a
./e/b
./e/5

あなたはかなり近かった、-nameオプションはベース名のみを考慮します-pathが、パス全体を考慮します=)


よくやった。ただし、OPが望んでいたことの1つ、で終わるファイルを見つけることを忘れていました_peaks.bed
アレックス2013年

2
これはGNUの多くの拡張機能を使用しますfindが、質問にはLinuxのタグが付けられているため、問題はありません。いい答えだ。
Jonathan Leffler 2013年

1
簡単な注意:.最初の検索プロンプトで使用する場合は、除外する各パスで使用する必要があります。パスマッチングはかなり厳密で、あいまい検索は行いません。したがって、使用すると機能find / -type f -name *.bed" ! -path "./tmp/"しなくなります。あなたは! -path "/tmp"それを幸せにする必要があります。
ピールマン2013年

3
*が重要であることに注意してください。$ ! -path "./directory/*"
トーマスベネット

3
マニュアルページによると、「ディレクトリツリー全体を無視するに-pruneは、ツリー内のすべてのファイルをチェックするのではなく、を使用します。」除外したディレクトリが非常に深く実行されているか、大量のファイルがあり、パフォーマンスが気になる場合は、-prune代わりにこのオプションを使用してください。
thdoan 2017

8

これがあなたがそれをすることができる1つの方法です...

find . -type f -name "*_peaks.bed" | egrep -v "^(./tmp/|./scripts/)"

2
これには、findGNUだけでなく、の任意のバージョンで作業できるというメリットがありますfind。ただし、質問にはLinuxのタグが付けられているため、重要ではありません。
Jonathan Leffler 2013年

2

使用する

find \( -path "./tmp" -o -path "./scripts" \) -prune -o  -name "*_peaks.bed" -print

または

find \( -path "./tmp" -o -path "./scripts" \) -prune -false -o  -name "*_peaks.bed"

または

find \( -path "./tmp" -path "./scripts" \) ! -prune -o  -name "*_peaks.bed"

順序は重要です。左から右に評価します。常にパスの除外から始めます。

説明

ディレクトリ全体を除外するために-not(または!)を使用しないでください。を使用し-pruneます。マニュアルで説明されているように:

−prune    The primary shall always evaluate as  true;  it
          shall  cause  find  not  to descend the current
          pathname if it is a directory.  If  the  −depth
          primary  is specified, the −prune primary shall
          have no effect.

そしてGNU検索マニュアルで:

-path pattern
              [...]
              To ignore  a  whole
              directory  tree,  use  -prune rather than checking
              every file in the tree.

実際、を使用すると-not -path "./pathname"、findは"./pathname"。の下の各ノードの式を評価します。

検索式は単なる条件評価です。

  • \( \)-グループ操作(を使用できますが-path "./tmp" -prune -o -path "./scripts" -prune -o、より冗長です)。
  • -path "./script" -prune-場合は-pathtrueを返し、ディレクトリで、そのディレクトリについてtrueを返すとないではない、それに降り。
  • -path "./script" ! -prune-として評価され(-path "./script") AND (! -prune)ます。プルーンの「常に真」を常に偽に戻します。"./script"一致としての印刷を回避します。
  • -path "./script" -prune -false--prune常にtrueを返すので、それに続いてと-false同じことを行うことができます!
  • -o-OR演算子。2つの式の間に演算子が指定されていない場合、デフォルトでAND演算子になります。

したがって、次のよう\( -path "./tmp" -o -path "./scripts" \) -prune -o -name "*_peaks.bed" -printに拡張されます。

[ (-path "./tmp" OR -path "./script") AND -prune ] OR ( -name "*_peaks.bed" AND print )

印刷は次のように展開されるため、ここでは重要です。

{ [ (-path "./tmp" OR -path "./script" )  AND -prune ]  OR (-name "*_peaks.bed" ) } AND print

-printfindによって追加されます-そのため、ほとんどの場合、式に追加する必要はありません。また、-prunetrueを返すため、「。/script」と「./tmp」を出力します。

-prune常にfalseを返すように切り替えたため、他の場合は必要ありません。

ヒント:を使用find -D opt expr 2>&1 1>/dev/nullして、最適化および拡張された方法を確認したり、
find -D search expr 2>&1 1>/dev/nullチェックされているパスを確認したりできます。


0

次のようなものを試してください

find . \( -type f -name \*_peaks.bed -print \) -or \( -type d -and \( -name tmp -or -name scripts \) -and -prune \)

少し間違えても驚かないでください。目標が(印刷ではなく)幹部である場合は、代わりに使用してください。


0

私にとって、このソリューションはfindを使用したコマンドexecで機能しませんでした。理由はよくわかりません。したがって、私のソリューションは

find . -type f -path "./a/*" -prune -o -path "./b/*" -prune -o -exec gzip -f -v {} \;

説明: sampson-chenのものと同じですが、

-prune-の手順パスを無視します...

-o-一致するものがない場合は、結果を出力します(ディレクトリを整理し、残りの結果を出力します)

18:12 $ mkdir a b c d e
18:13 $ touch a/1 b/2 c/3 d/4 e/5 e/a e/b
18:13 $ find . -type f -path "./a/*" -prune -o -path "./b/*" -prune -o -exec gzip -f -v {} \;

gzip: . is a directory -- ignored
gzip: ./a is a directory -- ignored
gzip: ./b is a directory -- ignored
gzip: ./c is a directory -- ignored
./c/3:    0.0% -- replaced with ./c/3.gz
gzip: ./d is a directory -- ignored
./d/4:    0.0% -- replaced with ./d/4.gz
gzip: ./e is a directory -- ignored
./e/5:    0.0% -- replaced with ./e/5.gz
./e/a:    0.0% -- replaced with ./e/a.gz
./e/b:    0.0% -- replaced with ./e/b.gz

受け入れられた答えは機能しませんでしたが、これは機能します。プルーンを使用して、find . -path ./scripts -prune -name '*_peaks.bed' -type f。複数のディレクトリを除外する方法がわからない。これには、type指定されている場合でも、最上位の除外ディレクトリも一覧表示されます。pruneを使用して検索操作を高速化する場合を除いて、Grep経由での除外はより簡単に思えます。
モーニッシュ2017

複数のディレクトリを除外するのにも苦労しましたが、上記のコメントでうまくいきました。'-not -path'の複数のインスタンスを使用し、各パス式に 'find'の最初のパラメーターで使用される完全なプレフィックスを含め、それぞれをアスタリスクで終了します(ドットをエスケープします)。
ジェットセット

0

以下を試すことができます:

find ./ ! \( -path ./tmp -prune \) ! \( -path ./scripts -prune \) -type f -name '*_peaks.bed'

2
そのような古い質問(4年!)で、コードを「ダンプ」するだけでなく、この新しい答えが優れている、または異なる理由を説明したいと思います。
nic3500 2017
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.