“find”无法执行条件深度搜索

“find”无法执行条件深度搜索


如果找到的内容位于当前目录中,则尝试让“查找”执行条件深度搜索。找到的是一个文件,然后用语言解释它的输出,否则像平常一样输出

$ find ~+ -maxdepth 1 \( -type f -printf 'File: %p\n' -o  -printf '%p\n' \) -o -mindepth 2 -printf '%p\n'

find: warning: you have specified the -mindepth option after a non-option argument (, but options are not positional (-mindepth affects tests specified before it as well as those specified after it)..

为什么失败以及如何解决这样的需求条件?

答案1

-maxdepth/ -mindepth(一个非标准的 GNU 扩展,尽管现在被很多其他find实现支持)不是状况谓词,它们是影响下降到目录的方式的全局标志find

可以通过和 的-maxdepth组合来实现标准的效果-path-prune

FreeBSD 的find必须-depth n/-n/+匹配深度n/ < n/>的文件n,因此在 FreeBSD 或衍生产品(macOS、DragonFly BSD ...)上,它只是:

find ~+ -depth 1 -type f -exec printf 'File: %s' {} ';' -o -print

这里使用-exec printf代替 GNU 特定的-printf.

从技术上讲,printf可能会失败,从而触发-print.使用-exec ... {} +代替-exec ... {} ';'可以解决这个问题,但会影响显示顺序。或者可以改为:

find ~+ -depth 1 -type f '(' -exec printf 'File: %s' {} ';' -o -true ')' -o -print

或者:

find ~+ '(' ! -depth 1 -o ! -type f ')' -print -o -exec printf 'File: %s' {} ';'

标准情况下,-path可以使用它来代替(尽管不是那么简单)。

LC_ALL=C find ~+/. -path '*/./*/*' -print -o \
  -type f -printf 'File: %p\n' -o -print

或者将深度限制为 2 (如我答案的早期版本,我认为你-mindepth 2-maxdepth 2

LC_ALL=C find ~+/. -path '*/./*/*' -prune -print -o \
  -type f -printf 'File: %p\n' -o -print

(仍然不是标准,因为-printfGNU 特定)。

我们附加/.到路径(否则保证不会出现在$PWD/中),以标记s~+的深度 0 点。find-path

你不能使用-path "$PWD/*/*"代替(如您建议的编辑$PWD),因为这对于包含通配符或反斜杠的值无法正常工作(因为-path将其参数视为通配符模式)。

比较:

$ mkdir -p '[1]/2/3/4'
$ touch '[1]/2/3/4/file'
$ cd '[1]'
$ LC_ALL=C find ~+ -path "$PWD/*/*" -print -o -type f -printf 'File: %p\n' -o -print
/tmp/[1]
/tmp/[1]/2
/tmp/[1]/2/3
/tmp/[1]/2/3/4
File: /tmp/[1]/2/3/4/file
$ LC_ALL=C find ~+/. -path '*/./*/*' -print -o -type f -printf 'File: %p\n' -o -print
/tmp/[1]/.
/tmp/[1]/./2
/tmp/[1]/./2/3
/tmp/[1]/./2/3/4
/tmp/[1]/./2/3/4/file

另一种方法是追加//,尽管这种方法的可移植性较差,因为某些find实现会删除那些多余的尾随/

您可以通过管道来sed 's:/\./:/:'删除/./输出中的那些内容。

LC_ALL=CGNU 需要它find,无法*匹配包含不形成有效字符的字节序列的路径组件。


虽然 GNUfind没有谓词来显式匹配文件的深度,但它的-printf谓词可以打印那个深度。所以在这里,你可以将该File:前缀添加到深度为 1 的常规文件中,并进行一些后期处理:

find . -printf '%d%y,%p\0' | # print depth, type and path
  sed -z 's/^1f,/&File: /' | # add "File: " prefix for regulars at depth 1  
  cut -zd, -f2-            | # remove the depth and type
  tr '\0' '\n'               # NL delimited for user consumption

相关内容