Bash - 使用 find 命令排除子目录
Bash - Excluding subdirectories using the find command
我正在使用查找命令获取特定文件所在的文件夹列表。但是由于某些子目录的权限被拒绝错误,我想排除某个子目录名称。
我已经尝试过我在这里找到的这些解决方案:
find /path/to/folders -path "*/noDuplicates" -prune -type f -name "fileName.txt"
find /path/to/folders ! -path "*/noDuplicates" -type f -name "fileName.txt"
以及这些命令的一些变体(例如路径名的变体)。
在第一种情况下它根本找不到文件夹,在第二种情况下我再次收到错误,所以我猜它仍然会尝试访问该目录。有谁知道我做错了什么或者有人对此有不同的解决方案?
问题在于 find
计算您传递给 -path
选项的表达式的方式。
相反,您应该尝试类似的方法:
find /path/to/folders ! -path "*noDuplicates*" -type f -name "fileName.txt"
根据我之前的评论,这适用于我的 Debian:
find . -path ./ignored_directory -prune -o -name fileName.txt -print
或
find /path/to/folder -path "*/ignored_directory" -prune -o -name fileName.txt -print
或
find /path/to/folder -name fileName.txt -not -path "*/ignored_directory/*"
对差异进行了很好的辩论here
编辑(添加了行为规范详细信息)
正在删除查找中的所有权限被拒绝的目录
使用 gnufind。
规范行为细节 - 在这个解决方案中我们想要:
- 排除不可读的目录内容(修剪它们),
- 避免 "permission denied" 来自不可读目录的错误,
- 保留其他错误和 return 状态,但
- 处理所有文件(即使是不可读的文件,如果我们能读出它们的名字)
基本设计模式是:
find ... \( -readable -o -prune \) ...
例子
find /var/log/ \( -readable -o -prune \) -name "*.1"
\谢谢{mklement0}
为了补充 并解决 OP 在 对 -o
的需求的困惑:
-prune
,作为每个 find
主要(动作或测试,在 GNU 语言中),returns 一个 布尔值,以及那个布尔值在 -prune
. 的情况下 总是 true
- 没有显式运算符,初选与
-a
(-and
) 隐式连接,它像它的兄弟 -o
(-or
) 一样执行 短路 布尔逻辑。
-a
的优先级高于 -o
.
有关所有 find
概念的摘要,请参阅
因此,接受的答案,
find . -path ./ignored_directory -prune -o -name fileName.txt -print
等价于(括号用于明确计算优先级):
find . \( -path ./ignored_directory -a -prune \) \
-o \
\( -name fileName.txt -a -print \)
由于短路应用,计算如下:
- 匹配
./ignored_directory
的输入路径导致 -prune
被评估;因为 -prune
总是 returns true
,短路会阻止计算 -o
运算符的 right 侧;实际上,没有任何反应(输入路径被忽略)
- 输入路径不匹配
./ignored_directory
,立即 - 再次由于短路 - 在 -o
的 右侧 侧继续评估:
- 只有当输入路径的文件名部分与
fileName.txt
匹配时,才会对 -print
进行主要评估;实际上,只打印文件名匹配 fileName.txt
的输入路径。
编辑:尽管我最初在这里声称,-print
需要在 -o
的右侧这里;没有它,implied -print
将应用于 entire 表达式,因此 also 打印左手手边匹配;请参阅下面的背景信息。
相比之下,让我们考虑一下 错误地不使用 -o
会造成什么影响:
find . -path ./ignored_directory -prune -name fileName.txt -print
这相当于:
find . -path ./ignored_directory -a -prune -a -name fileName.txt -a -print
这将仅打印修剪路径(也匹配-name
过滤器),因为-name
和 -print
初选(隐含地)与逻辑与连接;
在这种特定情况下,由于 ./ignored_directory
也不能匹配 fileName.txt
,因此 什么都不会打印 ,但是如果 -path
的参数是 glob,它是可能得到输出。
关于 find
的 隐式 使用 -print
:
POSIX mandates 如果 find
命令的表达式作为一个整体不包含任何一个
- 产出初选,例如
-print
本身
- 执行某事的初选,例如
-exec
和-ok
- (给出的示例初选对于 POSIX 规范来说是详尽无遗的。
find
,但现实世界的实现如 GNU find
和 BSD find
添加其他的,例如产生输出的 -print0
主,以及执行 -execdir
主)
-print
应用隐式,就好像表达式已被指定为:
\( expression \) -print
这很方便,因为它允许您编写 find .
之类的命令,而无需附加 -print
.
但是,在某些情况下,需要明确的-print
,例如这里的情况:
假设我们没有在接受的答案末尾指定 -print
:
find . -path ./ignored_directory -prune -o -name fileName.txt
由于表达式中现在没有输出生成或执行主体,因此它的计算结果为:
find . \( -path ./ignored_directory -prune -o -name fileName.txt \) -print
这不会按预期工作,因为如果 entire 括号表达式的计算结果为真,它将打印路径,在这种情况下错误地包括修剪目录。
相比之下,通过显式将 -print
附加到 -o
分支,仅当 -o
表达式的右侧计算结果为真时才打印路径;使用括号使逻辑更清晰:
find . -path ./ignored_directory -prune -o \( -name fileName.txt -print \)
相反,如果左侧为真,则仅执行 -prune
,不会产生任何输出(并且由于 overall 表达式包含 -print
,-print
未隐式应用)。
我正在使用查找命令获取特定文件所在的文件夹列表。但是由于某些子目录的权限被拒绝错误,我想排除某个子目录名称。 我已经尝试过我在这里找到的这些解决方案:
find /path/to/folders -path "*/noDuplicates" -prune -type f -name "fileName.txt"
find /path/to/folders ! -path "*/noDuplicates" -type f -name "fileName.txt"
以及这些命令的一些变体(例如路径名的变体)。 在第一种情况下它根本找不到文件夹,在第二种情况下我再次收到错误,所以我猜它仍然会尝试访问该目录。有谁知道我做错了什么或者有人对此有不同的解决方案?
问题在于 find
计算您传递给 -path
选项的表达式的方式。
相反,您应该尝试类似的方法:
find /path/to/folders ! -path "*noDuplicates*" -type f -name "fileName.txt"
根据我之前的评论,这适用于我的 Debian:
find . -path ./ignored_directory -prune -o -name fileName.txt -print
或
find /path/to/folder -path "*/ignored_directory" -prune -o -name fileName.txt -print
或
find /path/to/folder -name fileName.txt -not -path "*/ignored_directory/*"
对差异进行了很好的辩论here
编辑(添加了行为规范详细信息)
正在删除查找中的所有权限被拒绝的目录
使用 gnufind。
规范行为细节 - 在这个解决方案中我们想要:
- 排除不可读的目录内容(修剪它们),
- 避免 "permission denied" 来自不可读目录的错误,
- 保留其他错误和 return 状态,但
- 处理所有文件(即使是不可读的文件,如果我们能读出它们的名字)
基本设计模式是:
find ... \( -readable -o -prune \) ...
例子
find /var/log/ \( -readable -o -prune \) -name "*.1"
\谢谢{mklement0}
为了补充 -o
的需求的困惑:
-prune
,作为每个find
主要(动作或测试,在 GNU 语言中),returns 一个 布尔值,以及那个布尔值在-prune
. 的情况下 总是 - 没有显式运算符,初选与
-a
(-and
) 隐式连接,它像它的兄弟-o
(-or
) 一样执行 短路 布尔逻辑。 -a
的优先级高于-o
.
true
有关所有 find
概念的摘要,请参阅
因此,接受的答案,
find . -path ./ignored_directory -prune -o -name fileName.txt -print
等价于(括号用于明确计算优先级):
find . \( -path ./ignored_directory -a -prune \) \
-o \
\( -name fileName.txt -a -print \)
由于短路应用,计算如下:
- 匹配
./ignored_directory
的输入路径导致-prune
被评估;因为-prune
总是 returnstrue
,短路会阻止计算-o
运算符的 right 侧;实际上,没有任何反应(输入路径被忽略) - 输入路径不匹配
./ignored_directory
,立即 - 再次由于短路 - 在-o
的 右侧 侧继续评估:- 只有当输入路径的文件名部分与
fileName.txt
匹配时,才会对-print
进行主要评估;实际上,只打印文件名匹配fileName.txt
的输入路径。
- 只有当输入路径的文件名部分与
编辑:尽管我最初在这里声称,-print
需要在 -o
的右侧这里;没有它,implied -print
将应用于 entire 表达式,因此 also 打印左手手边匹配;请参阅下面的背景信息。
相比之下,让我们考虑一下 错误地不使用 -o
会造成什么影响:
find . -path ./ignored_directory -prune -name fileName.txt -print
这相当于:
find . -path ./ignored_directory -a -prune -a -name fileName.txt -a -print
这将仅打印修剪路径(也匹配-name
过滤器),因为-name
和 -print
初选(隐含地)与逻辑与连接;
在这种特定情况下,由于 ./ignored_directory
也不能匹配 fileName.txt
,因此 什么都不会打印 ,但是如果 -path
的参数是 glob,它是可能得到输出。
关于 find
的 隐式 使用 -print
:
POSIX mandates 如果 find
命令的表达式作为一个整体不包含任何一个
- 产出初选,例如
-print
本身 - 执行某事的初选,例如
-exec
和-ok
- (给出的示例初选对于 POSIX 规范来说是详尽无遗的。
find
,但现实世界的实现如 GNUfind
和 BSDfind
添加其他的,例如产生输出的-print0
主,以及执行-execdir
主)
-print
应用隐式,就好像表达式已被指定为:
\( expression \) -print
这很方便,因为它允许您编写 find .
之类的命令,而无需附加 -print
.
但是,在某些情况下,需要明确的-print
,例如这里的情况:
假设我们没有在接受的答案末尾指定 -print
:
find . -path ./ignored_directory -prune -o -name fileName.txt
由于表达式中现在没有输出生成或执行主体,因此它的计算结果为:
find . \( -path ./ignored_directory -prune -o -name fileName.txt \) -print
这不会按预期工作,因为如果 entire 括号表达式的计算结果为真,它将打印路径,在这种情况下错误地包括修剪目录。
相比之下,通过显式将 -print
附加到 -o
分支,仅当 -o
表达式的右侧计算结果为真时才打印路径;使用括号使逻辑更清晰:
find . -path ./ignored_directory -prune -o \( -name fileName.txt -print \)
相反,如果左侧为真,则仅执行 -prune
,不会产生任何输出(并且由于 overall 表达式包含 -print
,-print
未隐式应用)。