使用find搜索*.js文件时,如何排除特定目录?
find . -name '*.js'
使用find搜索*.js文件时,如何排除特定目录?
find . -name '*.js'
当前回答
我想知道目录的数量,文件的大小(仅为当前目录的MB),而这段代码正是我想要的:-)
来源
- ... 2791037 Jun 2 2011 foo.jpg
- ... 1284734651 Mär 10 16:16 foo.tar.gz
- ... 0 Mär 10 15:28 foo.txt
d ... 4096 Mär 3 17:12 HE
d ... 4096 Mär 3 17:21 KU
d ... 4096 Mär 3 17:17 LE
d ... 0 Mär 3 17:14 NO
d ... 0 Mär 3 17:15 SE
d ... 0 Mär 3 17:13 SP
d ... 0 Mär 3 17:14 TE
d ... 0 Mär 3 19:20 UN
代码
format="%s%'12d\n"
find . -type d -not -path "./*/*" | wc -l | awk -v fmt=$format '{printf fmt, " Anzahl Ordner = ", $1-1}'
find . -type f -not -path "./*/*" | wc -l | awk -v fmt=$format '{printf fmt, " Anzahl Dateien = ", $1}'
du . -hmS --max-depth=0 | awk -v fmt=$format '{printf fmt, " Groesse (MB) = ", $1}'
注意:awk需要额外的format=“%s%12d\n”来格式化数字。
结果
Anzahl Ordner = 8
Anzahl Dateien = 3
Groesse (MB) = 1.228
其他回答
使用-prune主键。例如,如果要排除/其他:
find . -path ./misc -prune -o -name '*.txt' -print
要排除多个目录,请在括号中对它们进行“或”运算。
find . -type d \( -path ./dir1 -o -path ./dir2 -o -path ./dir3 \) -prune -o -name '*.txt' -print
而且,要在任何级别排除具有特定名称的目录,请使用-name primary而不是-path。
find . -type d -name node_modules -prune -o -name '*.json' -print
使用-prune选项。因此,类似于:
find . -type d -name proc -prune -o -name '*.js'
“-typed-name-proc-prune”只查找要排除的名为proc的目录。“-o”是“OR”运算符。
我在C源文件exclude*.o和exclude*.swp以及exclude(非常规文件)和exclude-dir输出中找到了函数名:
find . \( ! -path "./output/*" \) -a \( -type f \) -a \( ! -name '*.o' \) -a \( ! -name '*.swp' \) | xargs grep -n soc_attach
对于跳过目录的首选语法应该是什么,这里显然有些混乱。
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
find . -name '*.js' -\! -name 'glob-for-excluded-dir' -prune