我使用find
命令在当前子目录中搜索具有给定扩展名的所有文件,忽略某些目录路径:
find -L . \( -wholename "*/ignoredPath" -o -wholename "*/ignoredPath2" \) -prune -o -name "*.ext"
这工作得很好,但现在我想忽略除了其中一个精确子目录之外的另一条路径。如何在不列出所有要忽略的子目录的情况下执行此操作?
例如,如果我有以下文件夹树:
*/base/pathToIgnore1
*/base/subdir/requiredPath
*/base/subdir/pathToIgnore2
*/base/subdir/pathToIgnore3
*/base/pathToIgnore4
如何编写find
命令忽略base
除路径之外的所有子目录*/base/subdir/requiredPath
?
我尝试过类似的东西
find -L . \( -wholename "*/ignoredPath" -o -wholename "*/ignoredPath2" -o \( -wholename "*/base" -a ! -wholename "*/base/subdir/requiredPath" \) \) -prune -o -name "*.ext"
但它不起作用,所有base
子目录都被忽略。
答案1
find -L . \
\( -type d \
\( -path "*/ignore" -o -path "*/indeed" -o \
\( -path "*/subdir/*" ! -path "*/subdir/save" \
\) \
\) \
\) \
-prune -o -print
如果你想要额外的过滤器(比如-name "*.ext"
),你必须把它放在前面-print
。最后一部分看起来像这样
-prune -o \( -name "*.ext" \) -print
请注意,我更改了名称以便于书写和阅读。以 开头的名称i
将被忽略。s
将显示以 开头的名称。以 结尾的名称file
是文件。
我的树看起来像这样:
$ find -printf "%y %p\n"
d .
d ./base
d ./base/subdir
d ./base/subdir/inform
f ./base/subdir/inform/imagefile
d ./base/subdir/isolate
f ./base/subdir/isolate/individualfile
f ./base/subdir/whatwhatinthefile
d ./base/subdir/save
f ./base/subdir/save/soundfile
f ./base/superfile
d ./base/indeed
f ./base/indeed/itemfile
d ./base/show
f ./base/show/startfile
d ./base/ignore
f ./base/ignore/importantfile
上述命令的输出:
.
./base
./base/subdir
./base/subdir/whatwhatinthefile
./base/subdir/save
./base/subdir/save/soundfile
./base/superfile
./base/show
./base/show/startfile
请注意,whatwhatinthefile
在base/subdir
.如果您不想要这些文件,base/subdir
那么您必须明确排除它们。我尝试过,但命令行变得太难看了。
根据您的用例,定义如下 shell 函数可能会更容易:
contrivedfind() {
find -L . \
\( -type d \
\( -path "*/ignore" -o -path "*/indeed" -o -path "*/subdir" \
\) \
\) \
-prune -o -print
find -L ./base/subdir/save
}
现在输出是:
.
./base
./base/superfile
./base/show
./base/show/startfile
./base/subdir/save
./base/subdir/save/soundfile
与以前唯一不同的是缺少./base/subdir
条目。但我认为这对你来说并不重要,因为你无论如何都想过滤文件。
和以前一样,您必须-print
在第一个之前放置任何额外的过滤器find
,这次也在第二个的末尾放置find
。
答案2
你必须防止它*/base
本身被匹配:
编辑1:
find -L . -type d \
\( -wholename "*/ignoredPath" -o -wholename "*/ignoredPath2" -o \
\( -wholename "*/base/*" -a \
\( ! -wholename "*/base/subdir" -a ! -wholename "*/base/subdir/*" \) \) -o \
\( -wholename "*/base/subdir/*" -a \
\( ! -wholename "*/base/subdir/requiredPath" -a ! -wholename "*/base/subdir/requiredPath/*" \) \) \) \
-prune -o -print
这有点挑剔:它可以防止意外匹配subdir2
可能不存在的目录。但你永远不知道...:-)