是否可以在查找命令中选择性地应用最小深度?

Tom*_*son 7 find

我有一个文件层次结构,例如:

\n
data\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 debug.log\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 messages\n\xe2\x94\x82\xc2\xa0\xc2\xa0 \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 msg001.txt\n\xe2\x94\x82\xc2\xa0\xc2\xa0 \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 msg002.txt\n\xe2\x94\x82\xc2\xa0\xc2\xa0 \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 msg003.txt\n\xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 pictures\n    \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 msg002\n    \xe2\x94\x82\xc2\xa0\xc2\xa0 \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 pic001.jpg\n    \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 msg003\n        \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 pic001.jpg\n        \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 pic002.jpg\n
Run Code Online (Sandbox Code Playgroud)\n

我想找到所有文件以及前两层以下的所有目录(数据、数据/消息和数据/图片)。所有不属于层次结构固定结构一部分的事物(如果有意义的话)。

\n

我可以通过一次查找调用来完成此操作吗?

\n

我可以找到这些文件:

\n
$ find data -type f | sort\ndata/debug.log\ndata/messages/msg001.txt\ndata/messages/msg002.txt\ndata/messages/msg003.txt\ndata/pictures/msg002/pic001.jpg\ndata/pictures/msg003/pic001.jpg\ndata/pictures/msg003/pic002.jpg\n
Run Code Online (Sandbox Code Playgroud)\n

我可以找到目录:

\n
$ find data -mindepth 2 -type d | sort\ndata/pictures/msg002\ndata/pictures/msg003\n
Run Code Online (Sandbox Code Playgroud)\n

但我无法将这些结合起来,因为 -mindepth 是一个选项,而不是测试:

\n
$ find data -type f -o \\( -mindepth 2 -type d \\) | sort\nfind: warning: you have specified the -mindepth option after a non-option argument -type, but options are not positional (-mindepth affects tests specified before it as well as those specified after it). Please specify options before other arguments.\n\ndata/messages/msg001.txt\ndata/messages/msg002.txt\ndata/messages/msg003.txt\ndata/pictures/msg002\ndata/pictures/msg002/pic001.jpg\ndata/pictures/msg003\ndata/pictures/msg003/pic001.jpg\ndata/pictures/msg003/pic002.jpg\n
Run Code Online (Sandbox Code Playgroud)\n

(注意这里没有找到data/debug.log)

\n

有什么方法可以将层次结构的深度视为真正的测试吗?

\n

我能想到的最好的组合是在路径上使用正则表达式来识别目录的前两层:

\n
$ find data -type f -o \\( -type d -regextype posix-extended \\! -regex 'data(/[^/]+)?' \\) | sort\n
Run Code Online (Sandbox Code Playgroud)\n

ilk*_*chu 5

有什么方法可以将层次结构的深度视为真正的测试吗?

FreeBSD中有find ,它还有-depth N一个条件:

% find data -type f -o -depth +1 -type d |sort
data/debug.log
data/messages/msg001.txt
data/messages/msg002.txt
data/messages/msg003.txt
data/pictures/msg002
data/pictures/msg002/pic001.jpg
data/pictures/msg003
data/pictures/msg003/pic001.jpg
data/pictures/msg003/pic002.jpg
Run Code Online (Sandbox Code Playgroud)

(是的,这很容易与该-depth选项混淆。)

如果您知道属于“固定结构”的目录集(在我看来,如果结构确实是固定的,您应该知道),您可以排除这些目录:

% find data ! -path data ! -path data/messages ! -path data/pictures
...
Run Code Online (Sandbox Code Playgroud)

或与 grep 相同:

% find data | grep -vEe '^(data|data/(pictures|messages))$'
...
Run Code Online (Sandbox Code Playgroud)

(由于您已经使用默认输出格式find, 而不是find -print0,您的文件名可能不包含换行符)

  • 没有*一个* BSD `find`。不同 BSD 之间的“find”是不同的。那个“-深度[+-]n” AFAIK 是由 FreeBSD 引入的。例如,它在 NetBSD 或 OpenBSD 中不可用。 (2认同)

Sté*_*las 3

请注意,这-mindepth是一个非标准扩展(最初来自 GNU find,但后来添加到了一些其他实现中)。与 相反-maxdepth,它很容易用标准谓词来模拟。例如LC_ALL=C find . -path './*/*'模拟 GNU 的find . -mindepth 2.

所以在这里:

LC_ALL=C find data '(' -type d -path '*/*/*' -o -type f ')' -print0 |
  sort -z |
  tr '\0' '\n'
Run Code Online (Sandbox Code Playgroud)

find(除非您使用 NUL 分隔的记录,否则您无法通过管道传输to的输出sort,因为文件路径可以由多行组成。-print0并且-z是 GNU 扩展,-print0现在很常见(很快 POSIX),但-z不太常见)。

  • @aviro `*` 匹配零个或多个 *字符*,而文件路径由 1 个或多个除 0 之外的 *字节* 组成,这些字节不必组成用户区域设置中的字符。例如,在 GNU 系统上使用 GNU `find`(使用 GNU libc 的 `fnmatch()`),在使用 UTF-8 字符映射 `-name '*'` 的语言环境中,与使用 `touch` 创建的文件不匹配$'Ste\351phane'` (恰好是用 iso8859-1 aka latin1 而不是 UTF-8 编码的 Stéphane)或 `touch $'\x7f\x80'` (文件名不必是文本) (2认同)