Use find command but exclude files in two director

2020-05-11 08:18发布

问题:

I want to find files that end with _peaks.bed, but exclude files in the tmp and scripts folders.

My command is like this:

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

But it didn't work. The files in tmp and script folder will still be displayed.

Does anyone have ideas about this?

回答1:

Here's how you can specify that with find:

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

Explanation:

  • find . - Start find from current working directory (recursively by default)
  • -type f - Specify to find that you only want files in the results
  • -name "*_peaks.bed" - Look for files with the name ending in _peaks.bed
  • ! -path "./tmp/*" - Exclude all results whose path starts with ./tmp/
  • ! -path "./scripts/*" - Also exclude all results whose path starts with ./scripts/

Testing the Solution:

$ 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

You were pretty close, the -name option only considers the basename, where as -path considers the entire path =)



回答2:

Here is one way you could do it...

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


回答3:

Try something like

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

and don't be too surprised if I got it a bit wrong. If the goal is an exec (instead of print), just substitute it in place.



回答4:

for me, this solution didn't worked on a command exec with find, don't really know why, so my solution is

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

Explanation: same as sampson-chen one with the additions of

-prune - ignore the proceding path of ...

-o - Then if no match print the results, (prune the directories and print the remaining results)

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


回答5:

You can try below:

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