使用find命令但排除两个目录中的文件

时间:2013-01-03 02:21:32

标签: linux shell unix find

我想查找以_peaks.bed结尾的文件,但排除tmpscripts个文件夹中的文件。

我的命令是这样的:

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

但它没有用。 <{1}}和tmp文件夹中的文件仍会显示。

有没有人有这方面的想法?

6 个答案:

答案 0 :(得分:176)

以下是使用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考虑整个路径=)

答案 1 :(得分:8)

这是你可以做到的一种方式......

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

答案 2 :(得分: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-如果-path返回true并且是目录,则对该目录返回true,并且进入该目录。
  • -path "./script" ! -prune-评估为(-path "./script") AND (! -prune)。它将修剪的“始终为真”恢复为始终为假。这样可以避免将"./script"打印为匹配项。
  • -path "./script" -prune -false-由于-prune始终返回true,因此您可以在-false之后跟!一样。
  • -o-或运算符。如果两个表达式之间未指定运算符,则默认为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

-print由find添加-这就是为什么在大多数情况下,您不需要在表达式中添加它的原因。并且由于-prune返回true,因此它将打印“ ./script”和“ ./tmp”。

在其他情况下则没有必要,因为我们将-prune切换为始终返回false。

提示:您可以使用find -D opt expr 2>&1 1>/dev/null来查看其优化和扩展方式,
find -D search expr 2>&1 1>/dev/null查看已检查的路径。

答案 3 :(得分:0)

尝试类似

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

如果我有点不对,也不要太惊讶。如果目标是exec(而不是print),只需将其替换就位。

答案 4 :(得分:0)

对我来说,这个解决方案并没有在一个命令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

答案 5 :(得分:0)

您可以尝试以下内容:

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