我正在尝试为所有JavaScript文件运行 find 命令,但如何排除特定目录?
find
这是我们正在使用的 find 代码 .
for file in $(find . -name '*.js') do java -jar config/yuicompressor-2.4.2.jar --type js $file -o $file done
我使用 find 为 xgettext 提供了一个文件列表,并希望省略特定目录及其内容 . 我尝试了 -path 与 -prune 结合的许多排列,但无法完全排除我想要的目录 .
xgettext
-path
-prune
虽然我能够忽略我想要忽略的目录的内容,但是 find 然后将目录本身作为结果之一返回,这导致 xgettext 因此而崩溃(不接受目录;仅接受文件) .
我的解决方案是简单地使用 grep -v 跳过结果中我不想要的目录:
grep -v
find /project/directory -iname '*.php' -or -iname '*.phtml' | grep -iv '/some/directory' | xargs xgettext
无论是否有 find 的论证都能100%发挥作用,我无法肯定地说 . 在经历了一些头痛之后,使用 grep 是一个快速而简单的解决方案 .
grep
以前的答案都没有在Ubuntu上有用 . 试试这个:
find . ! -path "*/test/*" -type f -name "*.js" ! -name "*-min-*" ! -name "*console*"
我发现了这个here
这适合我在Mac上:
find . -name *.php -or -path "./vendor" -prune -or -path "./app/cache" -prune
对于以 php 为后缀的搜索名称,它将排除 vendor 和 app/cache dir .
php
vendor
app/cache
要排除多个目录:
find . -name '*.js' -not \( -path "./dir1" -o -path "./dir2/*" \)
要添加目录,请添加 -o -path "./dirname/*" :
-o -path "./dirname/*"
find . -name '*.js' -not \( -path "./dir1" -o -path "./dir2/*" -o -path "./dir3/*"\)
但是,如果要排除许多目录,也许你应该使用regular expression .
对于我需要的工作,这样工作,从root开始在所有服务器中找到 landscape.jpg 并排除 /var 目录中的搜索:
landscape.jpg
/var
find / -maxdepth 1 -type d | grep -v /var | xargs -I '{}' find '{}' -name landscape.jpg
find / -maxdepth 1 -type d 列出 / 中的所有 d irectories
find / -maxdepth 1 -type d
/
grep -v /var 从列表中排除`/ var'
grep -v /var
xargs -I '{}' find '{}' -name landscape.jpg 对列表中的每个目录/结果执行任何命令,如 find
xargs -I '{}' find '{}' -name landscape.jpg
这里有很多答案;我不愿意添加另一个,但我认为这些信息很有用 .
TLDR: 了解您的根目录并使用“ -prune ”选项从那里定制搜索 .
Background: 我有一个 rsnapshot ( rsync )备份位置, /mnt/Backups/ ,在搜索系统( / )文件时会引起麻烦,因为这些备份包含~4.5TB(terra)的文件!
rsnapshot
rsync
/mnt/Backups/
我还有 /mnt/Vancouver ,我的主要工作文件夹,TB文件,备份[ /mnt/Backups/ 和 /mnt/Vancouver/ 物理(冗余)安装在不同的驱动器上] .
/mnt/Vancouver
/mnt/Vancouver/
在这里的两个最佳答案(How to exclude a directory in find . command)中,我发现使用接受的答案搜索系统文件的速度要快得多 much .
这个
find / -path /mnt -prune -o -name "*libname-server-2.a*" -print
在~3-4秒内找到该文件;这个
find / -name "*libname-server-2.a*" -not -path "/mnt/*"
出现(?)来递归所有被排除的目录(所有已安装卷的深层嵌套 rsync 快照),因此它需要 forever . 我无休止地陷入困境 . 例如,如果我尝试搜索"time"( time find ... ),我会看到大量输出 - 表明 find 正在深入遍历"excluded"目录:
time find ...
... find: ‘/mnt/Backups/rsnapshot_backups/monthly.0/snapshot_root/var/lib/udisks2’: Permission denied ...
在排除目录( /mnt/ )或嵌套路径(`/ mnt / Backups')后附加正斜杠会导致搜索 again* 永远占用:
/mnt/
Slow:
find / -path /mnt/ -prune -o -name "*libname-server-2.a*" -print find / -path /mnt/Vancouver -prune -o -name "*libname-server-2.a*" -print
"SOLUTION"
这是最好的解决方案(所有这些都在几秒钟内执行) . 同样,我的目录结构是
/ :root
/mnt/Backups/ :多TB备份
/mnt/Vancouver/ :多TB工作目录(在单独的驱动器上备份到 /mnt/Backups ),我经常要搜索
/mnt/Backups
/home/* :其他挂载点/工作"drives"(例如 /home/victoria = ~ )
/home/*
/home/victoria
~
System files (/):
要快速查找系统文件,请排除 /mnt ( not /mnt/ 或 /mnt/Backups ,...):
/mnt
$ find / -path /mnt -prune -o -name "*libname-server-2.a*" -print /usr/lib/libname-server-2.a
在~3-4秒内找到该文件 .
Non-system files:
例如 . 快速找到我的两个工作"drives", /mnt/Vancouver/ 和/或 /home/victoria/ 中的一个文件 .
/home/victoria/
$ find /mnt/Vancouver/ -name "*04t8ugijrlkj.jpg" /mnt/Vancouver/temp/04t8ugijrlkj.jpg $ find /home/victoria -iname "*Untitled Document 1" /home/victoria/backups/shortcuts.bak.2016.11.02/Untitled Document 1 /home/victoria/Untitled Document 1
Backups:
例如 . 在我的每小时/每日/每周/每月备份之一中查找已删除的文件 .
$ find /mnt/Backups/rsnapshot_backups/daily.0 -name "*04t8ugijrlkj.jpg" /mnt/Backups/rsnapshot_backups/daily.0/snapshot_root/mnt/Vancouver/temp/04t8ugijrlkj.jpg
Aside: 在命令末尾添加-print会禁止排除目录的打印输出:
$ find / -path /mnt -prune -o -name "*libname-server-2.a*" /mnt /usr/lib/libname-server-2.a $ find / -path /mnt -prune -o -name "*libname-server-2.a*" -print /usr/lib/libname-server-2.a $
比 for 循环更好地使用 exec 动作:
for
exec
find . -path "./dirtoexclude" -prune \ -o -exec java -jar config/yuicompressor-2.4.2.jar --type js '{}' -o '{}' \;
对于每个匹配的文件, exec ... '{}' ... '{}' \; 将被执行一次,用当前文件名替换大括号 '{}' .
exec ... '{}' ... '{}' \;
'{}'
请注意,大括号用单引号括起来,以保护它们不被解释为shell脚本标点* .
*来自 find (GNU findutils) 4.4.2 手册页的示例部分
find (GNU findutils) 4.4.2
如果搜索目录有模式(在我的情况下大多数情况下);你可以像下面这样简单地做:
find ./n* -name "*.tcl"
在上面的例子中;它搜索以“n”开头的所有子目录 .
我更喜欢 -not 符号......它更具可读性:
-not
find . -name '*.js' -and -not -path directory
这是我用来排除某些路径的格式:
$ find ./ -type f -name "pattern" ! -path "excluded path" ! -path "excluded path"
我用它来查找不在“ . *”路径中的所有文件:
$ find ./ -type f -name "*" ! -path "./.*" ! -path "./*/.*"
find . -name '*.js' -\! -name 'glob-for-excluded-dir' -prune
find -name '*.js' -not -path './node_modules/*' -not -path './vendor/*'
似乎工作相同
find -name '*.js' -not \( -path './node_modules/*' -o -path './vendor/*' \)
并且更容易记住IMO .
一种选择是排除所有包含grep目录名的结果 . 例如:
find . -name '*.js' | grep -v excludeddir
-prune 肯定有效并且是最佳答案,因为它可以防止降级到要排除的目录 . -not -path 仍在搜索排除的目录,它只是没有't print the result, which could be an issue if the excluded dir is mounted network volume or you don't权限 .
-not -path
棘手的部分是 find 非常特别关于参数的顺序,所以如果你没有得到它们恰到好处,那么你的命令可能不起作用 . 参数的顺序通常是这样的:
find {path} {options} {action}
{path} :首先放入所有与路径相关的参数,如 . -path './dir1' -prune -o
{path}
. -path './dir1' -prune -o
{options} :将 -name, -iname, etc 作为此组中的最后一个选项时,我取得了最大的成功 . 例如 . -type f -iname '*.js'
{options}
-name, -iname, etc
-type f -iname '*.js'
{action} :使用 -prune 时,您需要添加 -print
{action}
-print
这是一个有效的例子:
# setup test mkdir dir1 dir2 dir3 touch dir1/file.txt; touch dir1/file.js touch dir2/file.txt; touch dir2/file.js touch dir3/file.txt; touch dir3/file.js # search for *.js, exclude dir1 find . -path './dir1' -prune -o -type f -iname '*.js' -print # search for *.js, exclude dir1 and dir2 find . \( -path './dir1' -o -path './dir2' \) -prune -o -type f -iname '*.js' -print
我发现C源文件中的函数名不包括* .o和排除* .swp和exclude(不是常规文件),并使用此命令排除dir输出:
find . \( ! -path "./output/*" \) -a \( -type f \) -a \( ! -name '*.o' \) -a \( ! -name '*.swp' \) | xargs grep -n soc_attach
对于FreeBSD用户:
find . -name '*.js' -not -path '*exclude/this/dir*'
有很多好的答案,我花了一些时间来理解命令的每个元素是什么以及它背后的逻辑 .
find . -path ./misc -prune -o -name '*.txt' -print
find将开始在当前目录中查找文件和目录,因此 find . .
find .
-o 选项代表逻辑OR,并将命令的两个部分分开:
-o
[ -path ./misc -prune ] OR [ -name '*.txt' -print ]
not ./misc目录中的任何目录或文件都不会通过第一个测试 -path ./misc . 但他们将针对第二个表达进行测试 . 如果它们的名称对应于模式 *.txt ,则会打印它们,因为 -print 选项 .
-path ./misc
*.txt
当find到达./misc目录时,此目录仅满足第一个表达式 . 因此 -prune 选项将应用于它 . 它告诉find命令 not 探索该目录 . 因此,./misc中的任何文件或目录都不会被find探索,也不会针对表达式的第二部分进行测试,也不会被打印 .
对于工作解决方案(在Ubuntu 12.04(精确穿山甲)上测试)...
find ! -path "dir1" -iname "*.mp3"
将在dir1子文件夹中搜索当前文件夹和子文件夹中的MP3文件 .
使用:
find ! -path "dir1" ! -path "dir2" -iname "*.mp3"
...排除dir1和dir2
这是唯一适合我的人 .
find / -name NameOfFile ! -path '*/Directory/*'
搜索“NameOfFile”,不包括“目录” . 强调星星* .
how-to-use-prune-option-of-find-in-sh是Laurence Gonsalves关于 -prune 如何工作的优秀答案 .
以下是通用解决方案:
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
为避免多次输入 /path/to/seach/ ,请将 find 包装在 pushd .. popd 对中 .
/path/to/seach/
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
我试过上面的命令,但没有一个使用“-prune”的人对我有用 . 最后我用下面的命令尝试了这个:
find . \( -name "*" \) -prune -a ! -name "directory"
这是因为 find TESTS pattern “* foo *”的文件:
find ! -path "dir1" ! -path "dir2" -name "*foo*"
但如果你不使用 pattern ( find 不 TEST 文件),它确实 NOT 工作 . 所以 find 没有使用它以前评估的“真" & "假”bools . 上述表示法不工作用例的示例:
find ! -path "dir1" ! -path "dir2" -type f
没有 find 测试!因此,如果您需要查找没有任何模式匹配的文件,请使用-prune . 此外,通过使用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
问候
使用剪枝开关,例如,如果要排除 misc 目录,只需在查找命令中添加 -path ./misc -prune -o :
misc
-path ./misc -prune -o
这是一个包含多个目录的示例:
find . -type d \( -path dir1 -o -path dir2 -o -path dir3 \) -prune -o -print
这里我们排除了dir1,dir2和dir3,因为在 find 表达式中它是一个动作,它作用于标准 -path dir1 -o -path dir2 -o -path dir3 (如果dir1或dir2或dir3),与 type -d 进行AND运算 . 进一步的行动是 -o print ,只是打印 .
-path dir1 -o -path dir2 -o -path dir3
type -d
-o print
如果 -prune 不适合您,则会:
find -name "*.js" -not -path "./directory/*"
您可以使用prune选项来实现此目的 . 例如:
find ./ -path ./beta/* -prune -o -iname example.com -print
或者反向grep“grep -v”选项:
find -iname example.com | grep -v beta
您可以在Linux find command exclude directories from searching中找到详细的说明和示例 .
使用-prune选项 . 所以,像:
find . -type d -name proc -prune -o -name '*.js'
'-type d -name proc -prune'仅查找名为proc的目录以进行排除 .'-o'是'OR'运算符 .
-path -prune方法也适用于路径中的通配符 . 这是一个find语句,它将找到服务于多个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 \)
对于那些不能使用 -path 或 -not 的旧版UNIX的用户
测试了SunOS 5.10 bash 3.2和SunOS 5.11 bash 4.4
find . -type f -name "*" -o -type d -name "*excluded_directory*" -prune -type f
我发现以下比其他提议的解决方案更容易推理:
find build -not \( -path build/external -prune \) -name \*.js
这来自一个实际的用例,我需要在wintersmith生成的一些文件上调用yui-compressor,但是遗漏了需要按原样发送的其他文件 .
里面 \( 和 \) 是一个匹配 exactly build/external 的表达式(例如,如果你做 find ./build 则不匹配 - 在这种情况下你需要将它改为 ./build/external ),并且在成功时将避免遍历下面的任何内容 . 然后将其分组为带有转义括号的单个表达式,并以 -not 为前缀,这将使 find 跳过与该表达式匹配的任何内容 .
\(
\)
build/external
find ./build
./build/external
有人可能会问是否添加 -not 不会重新出现 -prune 隐藏的所有其他文件,答案是否定的 . -prune 的工作方式是,一旦到达,该目录下面的文件将被永久忽略 .
这也很容易扩展,以添加额外的排除 . 例如:
find build -not \( -path build/external -prune \) -not \( -path build/blog -prune \) -name \*.js
这里显然有一些混淆,即跳过目录的首选语法应该是什么 .
GNU Opinion
To ignore a directory and the files under it, use -prune
From the GNU find man page
Reasoning
-prune 阻止 find 进入目录 . 只需指定 -not -path 仍然会进入跳过的目录,但只要 find 测试每个文件, -not -path 就会为false .
Issues with -prune
-prune 做了它的目的,但在使用它时仍然需要注意一些事情 .
find 打印已修剪的目录 .
TRUE 那's intended behavior, it just doesn' t进入它 . 要避免完全打印目录,请使用逻辑上省略它的语法 .
-prune 仅适用于 -print 且无其他操作 .
NOT TRUE . -prune 适用于除 -delete 之外的任何操作 . 为什么删除不起作用?要 -delete 工作,find需要以DFS顺序遍历目录,因为 -delete 将首先删除叶子,然后删除叶子的父级等...但是为了指定 -prune 有意义, find 需要命中目录并停止降序,这显然没有 -depth 或 -delete 开启 .
-delete
-depth
Performance
我在这个问题上设置了一个关于三个最高评价答案的简单测试(用 -exec bash -c 'echo $0' {} \; 替换 -print 以显示另一个动作示例) . 结果如下
-exec bash -c 'echo $0' {} \;
---------------------------------------------- # 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
Conclusion
f10bit's syntax和Daniel C. Sobral's syntax平均需要10-25ms才能运行 . GetFree's syntax,不使用 -prune ,耗时865ms . 所以,是的,这是一个相当极端的例子,但如果你关心运行时间并且正在做任何远程密集的事情,你应该使用 -prune .
注意Daniel C. Sobral's syntax执行了两个 -prune 语法中较好的一个;但是,我强烈怀疑这是一些缓存的结果,因为切换两次运行导致相反结果的顺序,而非修剪版本总是最慢 .
测试脚本
#!/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
30 回答
我使用
find
为xgettext
提供了一个文件列表,并希望省略特定目录及其内容 . 我尝试了-path
与-prune
结合的许多排列,但无法完全排除我想要的目录 .虽然我能够忽略我想要忽略的目录的内容,但是
find
然后将目录本身作为结果之一返回,这导致xgettext
因此而崩溃(不接受目录;仅接受文件) .我的解决方案是简单地使用
grep -v
跳过结果中我不想要的目录:无论是否有
find
的论证都能100%发挥作用,我无法肯定地说 . 在经历了一些头痛之后,使用grep
是一个快速而简单的解决方案 .以前的答案都没有在Ubuntu上有用 . 试试这个:
我发现了这个here
这适合我在Mac上:
对于以
php
为后缀的搜索名称,它将排除vendor
和app/cache
dir .要排除多个目录:
要添加目录,请添加
-o -path "./dirname/*"
:但是,如果要排除许多目录,也许你应该使用regular expression .
对于我需要的工作,这样工作,从root开始在所有服务器中找到
landscape.jpg
并排除/var
目录中的搜索:find / -maxdepth 1 -type d | grep -v /var | xargs -I '{}' find '{}' -name landscape.jpg
find / -maxdepth 1 -type d
列出/
中的所有 d irectoriesgrep -v /var
从列表中排除`/ var'xargs -I '{}' find '{}' -name landscape.jpg
对列表中的每个目录/结果执行任何命令,如find
这里有很多答案;我不愿意添加另一个,但我认为这些信息很有用 .
TLDR: 了解您的根目录并使用“
-prune
”选项从那里定制搜索 .Background: 我有一个
rsnapshot
(rsync
)备份位置,/mnt/Backups/
,在搜索系统(/
)文件时会引起麻烦,因为这些备份包含~4.5TB(terra)的文件!我还有
/mnt/Vancouver
,我的主要工作文件夹,TB文件,备份[/mnt/Backups/
和/mnt/Vancouver/
物理(冗余)安装在不同的驱动器上] .在这里的两个最佳答案(How to exclude a directory in find . command)中,我发现使用接受的答案搜索系统文件的速度要快得多 much .
这个
在~3-4秒内找到该文件;这个
出现(?)来递归所有被排除的目录(所有已安装卷的深层嵌套
rsync
快照),因此它需要 forever . 我无休止地陷入困境 . 例如,如果我尝试搜索"time"(time find ...
),我会看到大量输出 - 表明find
正在深入遍历"excluded"目录:在排除目录(
/mnt/
)或嵌套路径(`/ mnt / Backups')后附加正斜杠会导致搜索 again* 永远占用:Slow:
"SOLUTION"
这是最好的解决方案(所有这些都在几秒钟内执行) . 同样,我的目录结构是
/
:root/mnt/Backups/
:多TB备份/mnt/Vancouver/
:多TB工作目录(在单独的驱动器上备份到/mnt/Backups
),我经常要搜索/home/*
:其他挂载点/工作"drives"(例如/home/victoria
=~
)System files (/):
要快速查找系统文件,请排除
/mnt
( not/mnt/
或/mnt/Backups
,...):在~3-4秒内找到该文件 .
Non-system files:
例如 . 快速找到我的两个工作"drives",
/mnt/Vancouver/
和/或/home/victoria/
中的一个文件 .Backups:
例如 . 在我的每小时/每日/每周/每月备份之一中查找已删除的文件 .
Aside: 在命令末尾添加-print会禁止排除目录的打印输出:
比
for
循环更好地使用exec
动作:对于每个匹配的文件,
exec ... '{}' ... '{}' \;
将被执行一次,用当前文件名替换大括号'{}'
.请注意,大括号用单引号括起来,以保护它们不被解释为shell脚本标点* .
注意事项
*来自
find (GNU findutils) 4.4.2
手册页的示例部分如果搜索目录有模式(在我的情况下大多数情况下);你可以像下面这样简单地做:
在上面的例子中;它搜索以“n”开头的所有子目录 .
我更喜欢
-not
符号......它更具可读性:这是我用来排除某些路径的格式:
我用它来查找不在“ . *”路径中的所有文件:
似乎工作相同
并且更容易记住IMO .
一种选择是排除所有包含grep目录名的结果 . 例如:
-prune
肯定有效并且是最佳答案,因为它可以防止降级到要排除的目录 .-not -path
仍在搜索排除的目录,它只是没有't print the result, which could be an issue if the excluded dir is mounted network volume or you don't权限 .棘手的部分是
find
非常特别关于参数的顺序,所以如果你没有得到它们恰到好处,那么你的命令可能不起作用 . 参数的顺序通常是这样的:{path}
:首先放入所有与路径相关的参数,如. -path './dir1' -prune -o
{options}
:将-name, -iname, etc
作为此组中的最后一个选项时,我取得了最大的成功 . 例如 .-type f -iname '*.js'
{action}
:使用-prune
时,您需要添加-print
这是一个有效的例子:
我发现C源文件中的函数名不包括* .o和排除* .swp和exclude(不是常规文件),并使用此命令排除dir输出:
对于FreeBSD用户:
有很多好的答案,我花了一些时间来理解命令的每个元素是什么以及它背后的逻辑 .
find将开始在当前目录中查找文件和目录,因此
find .
.-o
选项代表逻辑OR,并将命令的两个部分分开:not ./misc目录中的任何目录或文件都不会通过第一个测试
-path ./misc
. 但他们将针对第二个表达进行测试 . 如果它们的名称对应于模式*.txt
,则会打印它们,因为-print
选项 .当find到达./misc目录时,此目录仅满足第一个表达式 . 因此
-prune
选项将应用于它 . 它告诉find命令 not 探索该目录 . 因此,./misc中的任何文件或目录都不会被find探索,也不会针对表达式的第二部分进行测试,也不会被打印 .对于工作解决方案(在Ubuntu 12.04(精确穿山甲)上测试)...
将在dir1子文件夹中搜索当前文件夹和子文件夹中的MP3文件 .
使用:
...排除dir1和dir2
这是唯一适合我的人 .
搜索“NameOfFile”,不包括“目录” . 强调星星* .
how-to-use-prune-option-of-find-in-sh是Laurence Gonsalves关于
-prune
如何工作的优秀答案 .以下是通用解决方案:
为避免多次输入
/path/to/seach/
,请将find
包装在pushd .. popd
对中 .我试过上面的命令,但没有一个使用“-prune”的人对我有用 . 最后我用下面的命令尝试了这个:
这是因为
find
TESTS pattern “* foo *”的文件:但如果你不使用 pattern (
find
不 TEST 文件),它确实 NOT 工作 . 所以find
没有使用它以前评估的“真" & "假”bools . 上述表示法不工作用例的示例:没有
find
测试!因此,如果您需要查找没有任何模式匹配的文件,请使用-prune . 此外,通过使用prunefind
总是更快,而它真的跳过该目录而不是匹配它或更好地不匹配它 . 所以在这种情况下使用类似的东西:要么:
问候
使用剪枝开关,例如,如果要排除
misc
目录,只需在查找命令中添加-path ./misc -prune -o
:这是一个包含多个目录的示例:
这里我们排除了dir1,dir2和dir3,因为在
find
表达式中它是一个动作,它作用于标准-path dir1 -o -path dir2 -o -path dir3
(如果dir1或dir2或dir3),与type -d
进行AND运算 . 进一步的行动是-o print
,只是打印 .如果
-prune
不适合您,则会:您可以使用prune选项来实现此目的 . 例如:
或者反向grep“grep -v”选项:
您可以在Linux find command exclude directories from searching中找到详细的说明和示例 .
使用-prune选项 . 所以,像:
'-type d -name proc -prune'仅查找名为proc的目录以进行排除 .
'-o'是'OR'运算符 .
-path -prune方法也适用于路径中的通配符 . 这是一个find语句,它将找到服务于多个git存储库的git服务器的目录,而忽略了git内部目录:
对于那些不能使用 -path 或 -not 的旧版UNIX的用户
测试了SunOS 5.10 bash 3.2和SunOS 5.11 bash 4.4
我发现以下比其他提议的解决方案更容易推理:
这来自一个实际的用例,我需要在wintersmith生成的一些文件上调用yui-compressor,但是遗漏了需要按原样发送的其他文件 .
里面
\(
和\)
是一个匹配 exactlybuild/external
的表达式(例如,如果你做find ./build
则不匹配 - 在这种情况下你需要将它改为./build/external
),并且在成功时将避免遍历下面的任何内容 . 然后将其分组为带有转义括号的单个表达式,并以-not
为前缀,这将使find
跳过与该表达式匹配的任何内容 .有人可能会问是否添加
-not
不会重新出现-prune
隐藏的所有其他文件,答案是否定的 .-prune
的工作方式是,一旦到达,该目录下面的文件将被永久忽略 .这也很容易扩展,以添加额外的排除 . 例如:
这里显然有一些混淆,即跳过目录的首选语法应该是什么 .
GNU Opinion
From the GNU find man page
Reasoning
-prune
阻止find
进入目录 . 只需指定-not -path
仍然会进入跳过的目录,但只要find
测试每个文件,-not -path
就会为false .Issues with -prune
-prune
做了它的目的,但在使用它时仍然需要注意一些事情 .find
打印已修剪的目录 .TRUE 那's intended behavior, it just doesn' t进入它 . 要避免完全打印目录,请使用逻辑上省略它的语法 .
-prune
仅适用于-print
且无其他操作 .NOT TRUE .
-prune
适用于除-delete
之外的任何操作 . 为什么删除不起作用?要-delete
工作,find需要以DFS顺序遍历目录,因为-delete
将首先删除叶子,然后删除叶子的父级等...但是为了指定-prune
有意义,find
需要命中目录并停止降序,这显然没有-depth
或-delete
开启 .Performance
我在这个问题上设置了一个关于三个最高评价答案的简单测试(用
-exec bash -c 'echo $0' {} \;
替换-print
以显示另一个动作示例) . 结果如下Conclusion
f10bit's syntax和Daniel C. Sobral's syntax平均需要10-25ms才能运行 . GetFree's syntax,不使用
-prune
,耗时865ms . 所以,是的,这是一个相当极端的例子,但如果你关心运行时间并且正在做任何远程密集的事情,你应该使用-prune
.注意Daniel C. Sobral's syntax执行了两个
-prune
语法中较好的一个;但是,我强烈怀疑这是一些缓存的结果,因为切换两次运行导致相反结果的顺序,而非修剪版本总是最慢 .测试脚本