查找名称中至​​少包含三个字符的所有 PDF

查找名称中至​​少包含三个字符的所有 PDF

我想找到名称(不包括扩展名)大于3的PDF文件。

$ find ~ -iregex ".{3,}/.pdf"

什么都不返回,但是

$ find ~ -iregex ".+/.pdf"

作品。

如何启用该{3,}变体?

答案1

这里使用标准通配符更容易:

find ~ -name '*???.[pP][dD][fF]'

或者通过一些find实现(那些支持的-regex也支持-iname):

find ~ -iname '*???.pdf'

对于任意数量的字符而不是3,您可能更愿意恢复到-iregex可用的位置(请参阅@斯蒂芬·基特的回答) 或者你可以使用zshor ksh93glob:

  • zsh:

    set -o extendedglob # best in ~/.zshrc
    printf '%s\n' ~/**/?(#c3,).(#i)pdf(D)
    

    (D)考虑隐藏文件和隐藏目录中的文件,例如 with find

    • (#cx,y)zsh正则表达式的通配符等价物{x,y}
    • (#i)对于不区分大小写的
    • ?任何单个字符的标准通配符(如 regexp .
    • **/:任意级子目录(包括0级)
  • ksh93:

    FIGNORE='@(.|..)' # to consider hidden files
    set -o globstar
    printf '%s\n' **/{3,}(?).~(i:pdf)
    
    • @(x|y): 类似于 regexp 的扩展 ksh 通配符运算符(x|y)
    • FIGNORE:控制全局忽略哪些文件的特殊变量。设置后,通常会忽略隐藏文件,但我们仍然希望忽略存在的目录条目...
    • {x,y}(z)isksh93相当于 regexp z{x,y}
    • ~(i:...): 不区分大小写的匹配。

Glob 在这里有一些额外的优点,因为您可以获得一个排序列表(您可以使用glob 限定符find禁用排序,或使用不同的排序标准),并且当文件名包含不形成有效字符的字节序列时也可以工作(例如例如,在使用 UTF-8 字符集的语言环境中,该方法将无法报告 a ,因为不是字符,因此与 regexp或通配符或GNU不匹配。zshoNfind$'St\xE9phane Chazelas - CV.pdf\xE9.?*find

答案2

假设你正在使用 GNU find(你可能就是这样,因为它-iregex是 GNU 的扩展)POSIXfind),-regex并且-iregex默认为 Emacs 正则表达式,它不识别{3,}.您需要使用该-regextype选项指定不同类型的正则表达式;此外,您需要调整正则表达式以使其与完整路径匹配:

find ~ -regextype posix-extended -iregex '.*/[^/]{3,}.pdf'

您还应该转义.以便它与“.”匹配。而不是任何字符:

find ~ -regextype posix-extended -iregex '.*/[^/]{3,}\.pdf'

正则表达式可以简化,因为我们只关心三个非“/”字符:

find ~ -regextype posix-extended -iregex '.*[^/]{3}\.pdf'

为了完整起见,对于 FreeBSD 或 NetBSD find(另一种支持 的实现-iregex,不是你的,但如果.+没有 就无法工作-E),你可以这样写:

find ~ -iregex '.*[^/]\{3\}\.pdf'

或者:

find -E ~ -iregex '.*[^/]{3}\.pdf'

没有-E,那就是基本正则表达式(如grep)并与-E 扩展正则表达式(像grep -E)。

使用 ast-open 的find

find ~ -iregex '.*[^/]{3}\.pdf'

(这是开箱即用的扩展正则表达式)。

答案3

我怎么知道它们是 PDF?

除非你问,否则你不会。当然,我很迂腐,但你没有问文件.pdf名中带有。仅仅因为文件具有.pdf文件名中的字符不使其成为 PDF 文件

事实上,让我们对此一直迂腐一点:如果文件名的最后四个字符是.pdf,那么它的名称中始终包含三个以上的字符

所以这样做错误的方法,你可能会说:

$ find . -type f -name "*???.pdf"
./Documents/McLaren 720s Coupe:Order Summary.pdf
./Documents/Setup_MagicISO.exe.pdf

看到第二个了吗?它实际上是一个可执行文件。 (我知道,我改了名字。)而且我还丢失了一个 PDF 文件可以宣誓位于文档目录中...

$ ls Documents
McLaren 720s Coupe:Order Summary.pdf
Pioneer Premier DEH-P490IB CD Install Manual.PDF
Setup_MagicISO.exe.pdf

因此,-iname我们可以找到该文件,但仍然会出现这个非 PDF 文件。

我们真的在这种情况下要做的是检查文件的幻数使用file命令。一个选项输出MIME类型,这样解析起来更简单。然后查询find就变得简单了-name "???*"

$ find . -type f -name "???*" -print0|xargs -0 file --mime
./.bash_history:                                              text/plain; charset=us-ascii
./.bash_logout:                                               text/plain; charset=us-ascii
./.bashrc:                                                    text/plain; charset=us-ascii
./.profile:                                                   text/plain; charset=us-ascii
./Documents/McLaren 720s Coupe:Order Summary.pdf:             application/pdf; charset=binary
./Documents/Pioneer Premier DEH-P490IB CD Install Manual.PDF: application/pdf; charset=binary
./Documents/Setup_MagicISO.exe.pdf:                           application/x-dosexec; charset=binary
./Downloads/Setup_MagicISO.exe:                               application/x-dosexec; charset=binary
./Downloads/WindowsUpdate.diagcab:                            application/vnd.ms-cab-compressed; charset=binary

让我们使用冒号分隔符,并查找 MIME type application/pdf,然后将该部分清零并打印结果。请注意,我的一个文件的名称中有一个冒号;所以我不能只要求 awk ($2==":"){print $1}

$ find . -type f -name "???*" -print0|xargs -0 file --mime|awk -F: '($NF~"application/pdf"){OFS=":";$NF="";print}'|sed s/:$//
./Documents/McLaren 720s Coupe:Order Summary.pdf
./Documents/Pioneer Premier DEH-P490IB CD Install Manual.PDF

a现在,让我们通过设法包含名为和 的PDF 文件来完成abc

$ mkdir Documents/other
$ cp -a Documents/McLaren\ 720s\ Coupe\:Order\ Summary.pdf Documents/other/a
$ cp -a Documents/Pioneer\ Premier\ DEH-P490IB\ CD\ Install\ Manual.PDF  Documents/other/abc
$ find . -type f -name "???*" -print0|xargs -0 file --mime|awk -F: '($NF~"application/pdf"){OFS=":";$NF="";print}'|sed s/:$//
./Documents/McLaren 720s Coupe:Order Summary.pdf
./Documents/Pioneer Premier DEH-P490IB CD Install Manual.PDF
./Documents/other/abc

就这样。我知道我可能会因为过于迂腐而受到批评,但是在我的工作中面对数以千计的 NFS 卷和各种命名不当的文件,我希望更多的人会迂腐。

编辑添加:在现实世界中,我可能想利用它来updatedb构建可搜索的文件索引,locate而不是find读取该索引,而parallel不是xargs线程化。但这有点超出了这个问题的范围。我也是板着脸写的。我为什么这么关心?我可能正在寻找电影和音频文件;或某些类型的照片;或项目数据目录中的二进制可执行文件。

相关内容