找到文件名不是在Unix上的特定扩展名结束?

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

UNIX/GNU find,尽管它很强大,但似乎没有exclude模式(或者我错过了它),而且我总是发现很难使用正则表达式来找到匹配特定表达式的东西。

我在Windows环境中(使用大多数GNU工具的GnuWin32端口),所以我对Windows专用解决方案同样开放。

189400 次浏览

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

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

grep上的-v标志特别表示“查找与匹配的表达式”。

find . ! \( -name "*.exe" -o -name "*.dll" \)
$ find . -name \*.exe -o -name \*.dll -o -print

前两个name选项没有-print选项,所以跳过了。其他的都打印出来了。

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

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

还有一个:-)

$ ls -ltr
total 10
-rw-r--r--    1 scripter     linuxdumb         47 Dec 23 14:46 test1
-rw-r--r--    1 scripter     linuxdumb          0 Jan  4 23:40 test4
-rw-r--r--    1 scripter     linuxdumb          0 Jan  4 23:40 test3
-rw-r--r--    1 scripter     linuxdumb          0 Jan  4 23:40 test2
-rw-r--r--    1 scripter     linuxdumb          0 Jan  4 23:41 file5
-rw-r--r--    1 scripter     linuxdumb          0 Jan  4 23:41 file4
-rw-r--r--    1 scripter     linuxdumb          0 Jan  4 23:41 file3
-rw-r--r--    1 scripter     linuxdumb          0 Jan  4 23:41 file2
-rw-r--r--    1 scripter     linuxdumb          0 Jan  4 23:41 file1
$ find . -type f ! -name "*1" ! -name "*2" -print
./test3
./test4
./file3
./file4
./file5
$


Unix查找命令参考

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样式是最强大的样式。

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

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

如果你有一个很长的扩展列表——维护一个很长的-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代替。

find  /data1/batch/source/export   -type f -not  -name "*.dll" -not -name "*.exe"

与-regex一起使用-not

find . -type f -not -regex '.*\.\(exe\|dll\)'