在 Unix 上查找不以特定扩展名结尾的文件名?

Posted

技术标签:

【中文标题】在 Unix 上查找不以特定扩展名结尾的文件名?【英文标题】:find filenames NOT ending in specific extensions on Unix? 【发布时间】:2010-11-23 09:51:30 【问题描述】:

有没有一种简单的方法可以递归地查找目录层次结构中的所有文件, 以扩展名列表结尾?例如。所有不是 *.dll 或 *.exe 的文件

UNIX/GNU find,虽然功能强大,但似乎没有exclude 模式(或者我错过了它),而且我一直发现很难使用正则表达式来查找不匹配特定的表达式。

我在 Windows 环境中(使用大多数 GNU 工具的GnuWin32 端口),所以我同样愿意接受仅限 Windows 的解决方案。

【问题讨论】:

这个问题在这里有更多答案:List files not matching a pattern? 【参考方案1】:

或者没有( 并且需要转义它:

find . -not -name "*.exe" -not -name "*.dll"

并且还排除目录列表

find . -not -name "*.exe" -not -name "*.dll" -not -type d

或正逻辑;-)

find . -not -name "*.exe" -not -name "*.dll" -type f

【讨论】:

-not 可以替换为'!'(推荐引用)。另一方面,-name 区分大小写,而 -iname 不区分大小写。【参考方案2】:
find . ! \( -name "*.exe" -o -name "*.dll" \)

【讨论】:

在 Solaris 上 -not 是一个糟糕的选择,这个带有 ! 的效果很好:)【参考方案3】:
$ find . -name \*.exe -o -name \*.dll -o -print

前两个 -name 选项没有 -print 选项,因此它们被跳过。其他所有内容均已打印。

【讨论】:

【参考方案4】:

你可以使用 grep 命令做一些事情:

find . | grep -v '(dll|exe)$'

grep 上的 -v 标志专门表示“查找与此表达式匹配的内容。”

【讨论】:

grep -v '\.(dll|exe)$' 例如,会阻止匹配名为“dexe”的文件或目录 这只适用于扩展的正则表达式。我必须添加 -E(或使用 egrep)才能完成这项工作。 你可以使用两个表达式来代替-E: grep -v -e '\.dll$' -e '\.exe$'【参考方案5】:

还有一个:-)

$ ls -ltr
共 10 个
-rw-r--r-- 1 脚本编写者 linuxdumb 47 Dec 23 14:46 test1
-rw-r--r-- 1 脚本编写者 linuxdumb 0 Jan 4 23:40 test4
-rw-r--r-- 1 脚本编写者 linuxdumb 0 Jan 4 23:40 test3
-rw-r--r-- 1 脚本编写者 linuxdumb 0 Jan 4 23:40 test2
-rw-r--r-- 1 脚本编写者 linuxdumb 0 Jan 4 23:41 file5
-rw-r--r-- 1 脚本编写者 linuxdumb 0 Jan 4 23:41 file4
-rw-r--r-- 1 脚本编写者 linuxdumb 0 Jan 4 23:41 file3
-rw-r--r-- 1 脚本编写者 linuxdumb 0 Jan 4 23:41 file2
-rw-r--r-- 1 脚本编写者 linuxdumb 0 Jan 4 23:41 file1
$查找。 -类型 f ! -名称“*1”! -name "*2" -print
./test3
./test4
./文件3
./file4
./file5
$

Unix find command reference

【讨论】:

【参考方案6】:
find  /data1/batch/source/export   -type f -not  -name "*.dll" -not -name "*.exe"

【讨论】:

【参考方案7】:

Linux/OS X:

从当前目录开始,递归查找所有以.dll或.exe结尾的文件

find . -type f | grep -P "\.dll$|\.exe$"

从当前目录开始,递归查找所有不以.dll或.exe结尾的文件

find . -type f | grep -vP "\.dll$|\.exe$"

注意事项:

(1) grep 中的 P 选项表示我们正在使用 Perl 样式编写正则表达式,以便与 grep 命令结合使用。为了结合正则表达式执行 grep 命令,我发现 Perl 风格是最强大的风格。

(2) grep 中的 v 选项指示 shell 排除任何满足正则表达式的文件

(3) say ".dll$" 末尾的 $ 字符是一个分隔符控制字符,它告诉 shell 文件名字符串以 ".dll" 结尾

【讨论】:

【参考方案8】:

如果您有很长的扩展列表 - 维护一长串 -not -name 'this' -not -name 'that' -not -name 'other' 会很乏味且容易出错 - 或者如果搜索是程序化的并且扩展列表很长,则此页面上的其他解决方案是不可取的是在运行时构建的。

对于这些情况,可能需要更清楚地分离数据(扩展列表)和代码(find 的参数)的解决方案。给定一个如下所示的目录和文件结构:

.
└── a
    ├── 1.txt
    ├── 15.xml
    ├── 8.dll
    ├── b
    │   ├── 16.xml
    │   ├── 2.txt
    │   ├── 9.dll
    │   └── c
    │       ├── 10.dll
    │       ├── 17.xml
    │       └── 3.txt
    ├── d
    │   ├── 11.dll
    │   ├── 18.xml
    │   ├── 4.txt
    │   └── e
    │       ├── 12.dll
    │       ├── 19.xml
    │       └── 5.txt
    └── f
        ├── 13.dll
        ├── 20.xml
        ├── 6.txt
        └── g
            ├── 14.dll
            ├── 21.xml
            └── 7.txt

你可以这样做:

## data section, list undesired extensions here
declare -a _BADEXT=(xml dll)

## code section, this never changes
BADEXT="$( IFS="|" ; echo "$_BADEXT[*]" | sed 's/|/\\|/g' )"
find . -type f ! -regex ".*\.\($BADEXT\)"

结果:

./a/1.txt
./a/b/2.txt
./a/b/c/3.txt
./a/d/4.txt
./a/d/e/5.txt
./a/f/6.txt
./a/f/g/7.txt

您可以在不更改代码块的情况下更改扩展列表。

注意不适用于本机 OSX find - 请改用 gnu find。

【讨论】:

以上是关于在 Unix 上查找不以特定扩展名结尾的文件名?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用正则表达式匹配不以某些字符开头或结尾的单词?

在所有子目录中查找具有特定扩展名的文件数

查找特定文件名的扩展名

正则表达式 - 以特定字符串开头但不以另一个子字符串结尾

字符串的正则表达式,不以指定的子字符串结尾[重复]

.htaccess 中的重写引擎以捕获不以 html 结尾的文件