从查找中排除目录。 命令
我试图为所有JavaScript文件运行查找命令,但是如何排除特定目录?
这是我们使用的查找代码。
for file in $(find . -name '*.js'); do java -jar config/yuicompressor-2.4.2.jar --type js $file -o $file; done
例如,如果要排除misc
目录,只需将-path ./misc -prune -o
添加到find命令中,请使用prune开关:
find . -path ./misc -prune -o -name '*.txt' -print
这是一个多目录的例子:
find . -type d \( -path dir1 -o -path dir2 -o -path dir3 \) -prune -o -print
在这里,我们排除了dir1,dir2和dir3,因为在find
expression式中它是一个动作,作用于条件-path dir1 -o -path dir2 -o -path dir3
(如果dir1或dir2或dir3),用type -d
。 进一步的行动是-o print
,只是打印。
如果-prune
不适合你,这将会:
find -name "*.js" -not -path "./directory/*"
我发现以下比其他build议的解决scheme更容易推理:
find build -not \( -path build/external -prune \) -name \*.js
这来自一个实际的用例,我需要在由wintersmith生成的一些文件上调用yui-compressor,但是忽略了其他需要按原样发送的文件。
Inside \(
和\)
是一个完全匹配build/external
的expression式,并且在成功时避免遍历下面的任何东西 。 然后将这个分组作为一个带有转义括号的单个expression式,并以-not
作为前缀,这将使find
跳过与该expression式匹配的任何内容。
有人可能会问,如果添加-not
不会使所有其他文件隐藏在-prune
重新出现,答案是否定的。 -prune
工作方式是,任何一旦达到目录下的文件都被永久忽略。
这也很容易扩大增加排除。 例如:
find build -not \( -path build/external -prune \) -not \( -path build/blog -prune \) -name \*.js
这里显然有一些混淆,那就是跳过目录的首选语法应该是什么。
GNU的意见
To ignore a directory and the files under it, use -prune
从GNU查找手册页
推理
-prune
停止find
从一个目录下降。 只要指定-not -path
将仍然下降到跳过的目录中,但是不论何时find
testing每个文件,都不会使用-not -path
。
与-prune
问题
普-prune
做它的意图,但仍然有些事情,你必须照顾使用它。
-
find
打印修剪的目录。- TRUE这是预期的行为,它只是不下降。 要避免完全打印目录,请使用逻辑上省略的语法。
-
-prune
只能使用-print
而不需要其他操作。- 不是真的 。 除了
-delete
之外,-prune
可以使用任何操作。 为什么不使用删除? 对于删除工作,find需要以DFS顺序遍历目录,因为-delete
将首先删除叶子,然后叶子的父母等…但是为了指定-prune
有意义,find
需要打到目录并停止降级,这显然与-depth
或-delete
-depth
。
- 不是真的 。 除了
性能
我为这个问题设置了一个简单的testing(用-exec bash -c 'echo $0' {} \;
-c'echo -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的语法在两个语法中执行得更好; 但是,我强烈怀疑这是一些caching的结果,因为切换两者的顺序导致相反的结果,而非修剪版本总是最慢的。
testing脚本
#!/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=$((es)) 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=$((es)) 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=$((es)) printf " [# of files] $name3_num [Runtime(ns)] $name3_perf\n\n" echo "Cleaning up test files..." cleanup
一个选项是排除包含目录名称的所有结果与grep。 例如:
find . -name '*.js' | grep -v excludeddir
我更喜欢-not
notation …它更可读:
find . -name '*.js' -and -not -path directory
使用-prune选项。 所以,像这样的:
find . -type d -name proc -prune -o -name '*.js'
'-type d -name proc -prune'只查找名为proc的目录以排除。
'-o'是一个'OR'运算符。
这是我用来排除某些path的格式:
$ find ./ -type f -name "pattern" ! -path "excluded path" ! -path "excluded path"
我用它来查找所有不在“。*”path中的文件:
$ find ./ -type f -name "*" ! -path "./.*" ! -path "./*/.*"
对于一个工作解决scheme(在Ubuntu 12.04(精确穿山甲)testing)…
find ! -path "dir1" -iname "*.mp3"
将在当前文件夹和子文件夹中search除dir1子文件夹以外的MP3文件。
使用:
find ! -path "dir1" ! -path "dir2" -iname "*.mp3"
…排除dir1和dir2
要排除多个目录:
find . -name '*.js' -not \( -path "./dir1" -o -path "./dir2/*" \)
要添加目录,请添加-o -path "./dirname/*"
:
find . -name '*.js' -not \( -path "./dir1" -o -path "./dir2/*" -o -path "./dir3/*"\)
但是也许你应该使用正则expression式 ,如果有很多目录要排除。
您可以使用修剪选项来实现此目的。 例如:
find ./ -path ./beta/* -prune -o -iname example.com -print
或者反转grep“grep -v”选项:
find -iname example.com | grep -v beta
您可以在Linux中查找详细的说明和示例查找命令排除search目录 。
我正在使用find
来提供xgettext
的文件列表,并希望省略特定的目录及其内容。 我尝试了许多与-prune
结合的-prune
但无法完全排除我想要去的目录。
虽然我可以忽略我想要忽略的目录的内容 ,但find
并返回目录本身作为结果之一,导致xgettext
作为结果崩溃(不接受目录;只有文件)。
我的解决scheme是简单地使用grep -v
跳过结果中我不想要的目录:
find /project/directory -iname '*.php' -or -iname '*.phtml' | grep -iv '/some/directory' | xargs xgettext
无论是否有一个可以100%发挥作用的论据,我都不能肯定地说。 使用grep
是一些头痛之后的快速简单的解决scheme。
find -name '*.js' -not -path './node_modules/*' -not -path './vendor/*'
好像和你一样工作
find -name '*.js' -not \( -path './node_modules/*' -o -path './vendor/*' \)
而且更容易记住IMO。
find . -name '*.js' -\! -name 'glob-for-excluded-dir' -prune
以前的答案在Ubuntu上都不是很好。 尝试这个:
find . ! -path "*/test/*" -type f -name "*.js" ! -name "*-min-*" ! -name "*console*"
我在这里find了
这适用于Mac上的我:
find . -name *.php -or -path "./vendor" -prune -or -path "./app/cache" -prune
它将排除vendor
和app/cache
目录search名称后缀的php
。
-path -prune方法也适用于path中的通配符。 下面是一个查找语句,它将查找git服务器的服务目录,这些目录服务于多个git存储库,而不是git内部目录:
find . -type d \ -not \( -path */objects -prune \) \ -not \( -path */branches -prune \) \ -not \( -path */refs -prune \) \ -not \( -path */logs -prune \) \ -not \( -path */.git -prune \) \ -not \( -path */info -prune \) \ -not \( -path */hooks -prune \)
如何使用修剪selectfind在sh是劳伦斯贡萨尔斯如何-prune
作品一个很好的答案。
这里是通用的解决scheme:
find /path/to/search \ -type d \ \( -path /path/to/search/exclude_me \ -o \ -name exclude_me_too_anywhere \ \) \ -prune \ -o \ -type f -name '*\.js' -print
为了避免多次input/path/to/seach/
,将find
包装在pushd .. popd
对中。
pushd /path/to/search; \ find . \ -type d \ \( -path ./exclude_me \ -o \ -name exclude_me_too_anywhere \ \) \ -prune \ -o \ -type f -name '*\.js' -print; \ popd
我发现在C源文件中的函数名称排除* .o和排除* .swp和排除(不是常规文件),并排除使用此命令的dir输出:
find . \( ! -path "./output/*" \) -a \( -type f \) -a \( ! -name '*.o' \) -a \( ! -name '*.swp' \) | xargs grep -n soc_attach
比for
循环更好地使用exec
操作:
find . -path "./dirtoexclude" -prune \ -o -exec java -jar config/yuicompressor-2.4.2.jar --type js '{}' -o '{}' \;
exec ... '{}' ... '{}' \;
将为每个匹配文件执行一次,用当前文件名replace大括号'{}'
。
请注意,大括号括在单引号,以防止他们解释为shell脚本标点* 。
笔记
*从find (GNU findutils) 4.4.2
手册页的EXAMPLES部分
这是因为find
模式 “ * foo * ”的文件:
find ! -path "dir1" ! -path "dir2" -name "*foo*"
但是如果你不使用模式 ( find
不testing文件),它就不起作用。 所以find
不使用它以前评估过的“ 真实 ”和“ 虚假 ”的布尔。 以上表示法不工作用例示例:
find ! -path "dir1" ! -path "dir2" -type f
没有find
testing! 所以如果你需要find没有任何模式匹配的文件,使用-prune。 另外,通过使用剪枝find
总是更快,而实际上跳过目录,而不是匹配它,或更好地不匹配它。 所以在这种情况下使用如下所示:
find dir -not \( -path "dir1" -prune \) -not \( -path "dir2" -prune \) -type f
要么:
find dir -not \( -path "dir1" -o -path "dir2" -prune \) -type f
问候
对于FreeBSD用户:
find . -name '*.js' -not -path '*exclude/this/dir*'
如果search目录有模式(在我的大多数情况下); 你可以简单地做如下:
find ./n* -name "*.tcl"
在上面的例子中, 它search以“n”开始的所有子目录。
我发现了这个页面上的build议,很多其他页面在我的Mac OS X系统上不起作用。 但是,我find了一个适合我的变体。
最大的想法是searchMacintosh HD,但避免遍历所有外部卷,这些卷主要是时间机器备份,映像备份,装入共享和归档,但不必将其全部卸载,这通常是不切实际的。
这是我的工作脚本,我已经命名为“findit”。
#!/usr/bin/env bash # inspired by http://stackoverflow.com/questions/4210042/exclude-directory-from-find-command Danile C. Sobral # using special syntax to avoid traversing. # However, logic is refactored because the Sobral version still traverses # everything on my system echo ============================ echo find - from cwd, omitting external volumes date echo Enter sudo password if requested sudo find . -not \( \ -path ./Volumes/Archive -prune -o \ -path ./Volumes/Boot\ OS\ X -prune -o \ -path ./Volumes/C \ -path ./Volumes/Data -prune -o \ -path ./Volumes/jas -prune -o \ -path ./Volumes/Recovery\ HD -prune -o \ -path ./Volumes/Time\ Machine\ Backups -prune -o \ -path ./Volumes/SuperDuper\ Image -prune -o \ -path ./Volumes/userland -prune \ \) -name "$1" -print date echo ============================ iMac2:~ jas$
各种path都与外部存档卷,Time Machine,虚拟机,其他挂载的服务器等有关。 一些卷名称中有空格。
一个好的testing运行是“findit index.php”,因为这个文件出现在我的系统的很多地方。 有了这个脚本,大约需要10分钟来search主硬盘。 没有这些排除,这需要很多小时。
我想知道目录的数量,文件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
不知道这是否会覆盖所有的边缘情况,但以下将是非常简单和直接的尝试:
ls -1|grep -v -e ddl -e docs| xargs rm -rf
这应该删除当前目录中的所有文件/目录excpet'ddls'和'docs'。
我尝试过上面的命令,但是没有一个使用“-prune”的人为我工作。 最终我用下面的命令试了一下:
find . \( -name "*" \) -prune -a ! -name "directory"