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

Han*_*Sun 82 unix linux shell find

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

我的命令是这样的:

 find . -type f \( -name "*_peaks.bed" ! -name "*tmp*" ! -name "*scripts*" \)
Run Code Online (Sandbox Code Playgroud)

但它没有用.文件夹tmpscript文件夹仍将显示.

有没有人有这个想法?

sam*_*hen 182

以下是如何指定find:

find . -type f -name "*_peaks.bed" ! -path "./tmp/*" ! -path "./scripts/*"
Run Code Online (Sandbox Code Playgroud)

说明:

  • 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
Run Code Online (Sandbox Code Playgroud)

你非常接近,该-name选项只考虑basename,其中-path考虑整个路径=)

  • 根据手册页:“要忽略整个目录树,请使用 `-prune` 而不是检查树中的每个文件。” 如果您排除的目录运行得非常深或有大量文件并且您关心性能,那么请改用`-prune` 选项。 (4认同)
  • 重要的是要注意*很重要.`$!-path"./directory/*"` (3认同)
  • 这在GNU`find`中使用了许多扩展,但由于问题标记为Linux,这不是问题.好答案. (2认同)
  • 简短说明:如果您在初始查找提示中使用“.”,则必须在排除的每个路径中使用它。路径匹配相当严格,不做模糊搜索。所以如果你使用 `find / -type f -name *.bed" ! -path "./tmp/"` 它不会工作。你需要有 `! -path "/tmp"` 才能让它满意。 (2认同)

f38*_*ric 18

使用

\n
find \\( -path "./tmp" -o -path "./scripts" \\) -prune -o  -name "*_peaks.bed" -print\n
Run Code Online (Sandbox Code Playgroud)\n

或者

\n
find \\( -path "./tmp" -o -path "./scripts" \\) -prune -false -o  -name "*_peaks.bed"\n
Run Code Online (Sandbox Code Playgroud)\n

或者

\n
find \\( -path "./tmp" -path "./scripts" \\) ! -prune -o  -name "*_peaks.bed"\n
Run Code Online (Sandbox Code Playgroud)\n

顺序很重要。它从左到右进行计算。\n始终从路径排除开始。

\n

解释

\n

不要使用-not(或!) 排除整个目录。使用-prune.\n如手册中所述:

\n
find \\( -path "./tmp" -o -path "./scripts" \\) -prune -o  -name "*_peaks.bed" -print\n
Run Code Online (Sandbox Code Playgroud)\n

并在 GNU 查找手册中:

\n
find \\( -path "./tmp" -o -path "./scripts" \\) -prune -false -o  -name "*_peaks.bed"\n
Run Code Online (Sandbox Code Playgroud)\n

事实上,如果您使用-not -path "./pathname",\nfind 将计算 下每个节点的表达式"./pathname"

\n

find 表达式只是条件评估。

\n
    \n
  • \\( \\)- 组操作(您可以使用-path "./tmp" -prune -o -path "./scripts" -prune -o,但它更详细)。
  • \n
  • -path "./script" -prune- 如果-path返回 true 并且是一个目录,则对该目录返回 true 并且不进入该目录。
  • \n
  • -path "./script" ! -prune- 它评估为(-path "./script") AND (! -prune). 它将 prune 的“始终为真”恢复为始终为假。它避免打印"./script"为匹配项。
  • \n
  • -path "./script" -prune -false- 由于-prunealways返回true,你可以跟随它来-false执行与than相同的操作!
  • \n
  • -o- 或运算符。如果两个表达式之间没有指定运算符,则默认为 AND 运算符。
  • \n
\n

因此,\\( -path "./tmp" -o -path "./scripts" \\) -prune -o -name "*_peaks.bed" -print扩展为:

\n
[ (-path "./tmp" OR -path "./script") AND -prune ] OR ( -name "*_peaks.bed" AND print )\n
Run Code Online (Sandbox Code Playgroud)\n

打印在这里很重要,因为如果没有它,它会扩展为:

\n
{ [ (-path "./tmp" OR -path "./script" )  AND -prune ]  OR (-name "*_peaks.bed" ) } AND print\n
Run Code Online (Sandbox Code Playgroud)\n

-print由 find 添加 - 这就是为什么大多数时候,您不需要将其添加到表达式中。由于-prune返回 true,它将打印“./script”和“./tmp”。

\n

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

\n

提示:你可以使用find -D opt expr 2>&1 1>/dev/null来查看它是如何优化和扩展的,
\nfind -D search expr 2>&1 1>/dev/null来查看检查了哪个路径。

\n


ale*_*lex 8

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

find . -type f -name "*_peaks.bed" | egrep -v "^(./tmp/|./scripts/)"
Run Code Online (Sandbox Code Playgroud)

  • 这有使用任何版本的`find`的优点,而不仅仅是使用GNU`find`.但是,问题是标记为Linux,因此并不重要. (2认同)