使用find搜索*.js文件时,如何排除特定目录?
find . -name '*.js'
使用find搜索*.js文件时,如何排除特定目录?
find . -name '*.js'
当前回答
如果有人想在Makefile中添加find命令,下面是我们排除目录的方法
! -路径“*/directoryName/*”
以下是格式化所有golang文件的示例,不包括protobuf go文件和供应商目录下的所有文件:
find . ! -name '*.pb.go' -name '*.go' ! -path "*/vendor/*" -exec gofmt -s -w '{}' +
其他回答
对于工作解决方案(在Ubuntu 12.04(精确穿山甲)上测试)。。。
find ! -path "dir1" -iname "*.mp3"
将在当前文件夹和子文件夹(dir1子文件夹除外)中搜索MP3文件。
Use:
find ! -path "dir1" ! -path "dir2" -iname "*.mp3"
…排除dir1和dir2
我发现以下内容比其他建议的解决方案更容易理解:
find build -not \( -path build/external -prune \) -name \*.js
# you can also exclude multiple paths
find build -not \( -path build/external -prune \) -not \( -path build/blog -prune \) -name \*.js
重要提示:在-path之后键入的路径必须与find在没有排除的情况下打印的路径完全匹配。如果这句话让您感到困惑,您只需确保在整个命令中使用完整路径,如下所示:find/full/path/-not\(-path/full/path/exclude/this-sprune\)。。。。如果您想更好地理解,请参见注释[1]。
Inside\(和\)是一个表达式,它将与build/external完全匹配(请参见上面的重要注释),并且在成功后,将避免遍历下面的任何内容。然后将其分组为带有转义括号的单个表达式,并以-not作为前缀,这将使find跳过该表达式匹配的任何内容。
有人可能会问,添加-not是否不会使所有其他被-previe隐藏的文件重新出现,答案是否定的。
这来自一个实际的用例,我需要对温特史密斯生成的一些文件调用yui压缩程序,但忽略了需要按原样发送的其他文件。
注[1]:如果您想排除/tmp/foo/bar,并且运行find时类似于“find/tmp\(…)”,那么您必须指定-path/tmp/foo/bar。另一方面,如果您运行find,类似于cd/tmp;find.\(…),那么必须指定-path。/foo/bbar。
您也可以使用
find -type f -not -name .directoryname -printf "%f\n"
我认为自己是一个狂欢爱好者,但是。。。在过去的两年中,我们没有找到一个适合bash用户的解决方案。我所说的“用户友好”是指只需一次调用,这不需要我记住复杂的语法+我可以使用与以前相同的find语法,因此以下解决方案最适合那些^^^
复制粘贴到shell中,并将~/.bash_aliases作为源代码:
cat << "EOF" >> ~/.bash_aliases
# usage: source ~/.bash_aliases , instead of find type findd + rest of syntax
findd(){
dir=$1; shift ;
find $dir -not -path "*/node_modules/*" -not -path "*/build/*" \
-not -path "*/.cache/*" -not -path "*/.git/*" -not -path "*/venv/*" $@
}
EOF
当然,为了添加或删除要排除的目录,您必须使用您选择的目录编辑此别名func。。。
对于跳过目录的首选语法应该是什么,这里显然有些混乱。
GNU意见
To ignore a directory and the files under it, use -prune
从GNU查找手册页
推理
-prune阻止find下降到目录中。仅指定-not-path仍将进入跳过的目录,但每当查找测试每个文件时,-not-paath将为false。
与-prune有关的问题
-梅干做了它想要做的事情,但在使用它时仍需要注意一些事情。
find打印修剪后的目录。TRUE这是预期的行为,它只是没有下降到目录中。为了避免完全打印目录,请使用逻辑上省略它的语法。-prune只适用于-print,不适用于其他操作。不正确-prune适用于除-delete之外的任何操作。为什么它不能与delete一起使用?要使-delete起作用,find需要按DFS顺序遍历目录,因为-delete将首先删除树叶,然后删除树叶的父级,等等。但是,要指定-sprune以使其合理,find必须命中一个目录并停止其降序,这显然在启用-dedepth或-delete时没有意义。
表演
我对这个问题的三个排名靠前的答案进行了简单的测试(用-exec bash-c'echo$0'{}\;替换-print以显示另一个动作示例)。结果如下
----------------------------------------------
# of files/dirs in level one directories
.performance_test/prune_me 702702
.performance_test/other 2
----------------------------------------------
> find ".performance_test" -path ".performance_test/prune_me" -prune -o -exec bash -c 'echo "$0"' {} \;
.performance_test
.performance_test/other
.performance_test/other/foo
[# of files] 3 [Runtime(ns)] 23513814
> find ".performance_test" -not \( -path ".performance_test/prune_me" -prune \) -exec bash -c 'echo "$0"' {} \;
.performance_test
.performance_test/other
.performance_test/other/foo
[# of files] 3 [Runtime(ns)] 10670141
> find ".performance_test" -not -path ".performance_test/prune_me*" -exec bash -c 'echo "$0"' {} \;
.performance_test
.performance_test/other
.performance_test/other/foo
[# of files] 3 [Runtime(ns)] 864843145
结论
f10bit的语法和Daniel C.Sobral的语法平均运行时间为10-25ms。GetFree的语法不使用-prune,耗时865ms。所以,是的,这是一个相当极端的例子,但如果您关心运行时间,并且正在做任何远程密集的事情,那么您应该使用-prune。
注意Daniel C.Sobral的语法在两种删减语法中表现得更好;但是,我强烈怀疑这是某些缓存的结果,因为切换两个运行的顺序会导致相反的结果,而非修剪版本总是最慢的。
测试脚本
#!/bin/bash
dir='.performance_test'
setup() {
mkdir "$dir" || exit 1
mkdir -p "$dir/prune_me/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/w/x/y/z" \
"$dir/other"
find "$dir/prune_me" -depth -type d -exec mkdir '{}'/{A..Z} \;
find "$dir/prune_me" -type d -exec touch '{}'/{1..1000} \;
touch "$dir/other/foo"
}
cleanup() {
rm -rf "$dir"
}
stats() {
for file in "$dir"/*; do
if [[ -d "$file" ]]; then
count=$(find "$file" | wc -l)
printf "%-30s %-10s\n" "$file" "$count"
fi
done
}
name1() {
find "$dir" -path "$dir/prune_me" -prune -o -exec bash -c 'echo "$0"' {} \;
}
name2() {
find "$dir" -not \( -path "$dir/prune_me" -prune \) -exec bash -c 'echo "$0"' {} \;
}
name3() {
find "$dir" -not -path "$dir/prune_me*" -exec bash -c 'echo "$0"' {} \;
}
printf "Setting up test files...\n\n"
setup
echo "----------------------------------------------"
echo "# of files/dirs in level one directories"
stats | sort -k 2 -n -r
echo "----------------------------------------------"
printf "\nRunning performance test...\n\n"
echo \> find \""$dir"\" -path \""$dir/prune_me"\" -prune -o -exec bash -c \'echo \"\$0\"\' {} \\\;
name1
s=$(date +%s%N)
name1_num=$(name1 | wc -l)
e=$(date +%s%N)
name1_perf=$((e-s))
printf " [# of files] $name1_num [Runtime(ns)] $name1_perf\n\n"
echo \> find \""$dir"\" -not \\\( -path \""$dir/prune_me"\" -prune \\\) -exec bash -c \'echo \"\$0\"\' {} \\\;
name2
s=$(date +%s%N)
name2_num=$(name2 | wc -l)
e=$(date +%s%N)
name2_perf=$((e-s))
printf " [# of files] $name2_num [Runtime(ns)] $name2_perf\n\n"
echo \> find \""$dir"\" -not -path \""$dir/prune_me*"\" -exec bash -c \'echo \"\$0\"\' {} \\\;
name3
s=$(date +%s%N)
name3_num=$(name3 | wc -l)
e=$(date +%s%N)
name3_perf=$((e-s))
printf " [# of files] $name3_num [Runtime(ns)] $name3_perf\n\n"
echo "Cleaning up test files..."
cleanup