使用find搜索*.js文件时,如何排除特定目录?

find . -name '*.js'

当前回答

TLDR:了解您的根目录,然后使用-path<excluded_path>-prine-o选项定制搜索。不要在排除路径的末尾包含尾随/。

例子:

find/-path/mnt-sprune-o-name“*libname-server-2.a*”-print


为了有效地使用find,我认为必须充分了解文件系统目录结构。在我的家用电脑上,我有多TB的硬盘,其中大约一半的内容使用rsnapshot(即rsync)进行备份。虽然备份到物理上独立(重复)的驱动器,但它安装在我的系统根目录(/)下:/mnt/Backups/rsnapshot_Backups/:

/mnt/Backups/
└── rsnapshot_backups/
    ├── hourly.0/
    ├── hourly.1/
    ├── ...
    ├── daily.0/
    ├── daily.1/
    ├── ...
    ├── weekly.0/
    ├── weekly.1/
    ├── ...
    ├── monthly.0/
    ├── monthly.1/
    └── ...

/mnt/Backups/rsnapshot_Backups/目录当前占用约2.9 TB,包含约60M个文件和文件夹;简单地遍历这些内容需要时间:

## As sudo (#), to avoid numerous "Permission denied" warnings:

time find /mnt/Backups/rsnapshot_backups | wc -l
60314138    ## 60.3M files, folders
34:07.30    ## 34 min

time du /mnt/Backups/rsnapshot_backups -d 0
3112240160  /mnt/Backups/rsnapshot_backups    ## 3.1 TB
33:51.88    ## 34 min

time rsnapshot du    ## << more accurate re: rsnapshot footprint
2.9T    /mnt/Backups/rsnapshot_backups/hourly.0/
4.1G    /mnt/Backups/rsnapshot_backups/hourly.1/
...
4.7G    /mnt/Backups/rsnapshot_backups/weekly.3/
2.9T    total    ## 2.9 TB, per sudo rsnapshot du (more accurate)
2:34:54          ## 2 hr 35 min

因此,每当我需要在我的/(根)分区上搜索文件时,我都需要处理(如果可能的话)遍历我的备份分区。


示例

在本主题中提出的各种方法(如何在find.command中排除目录)中,我发现使用公认的答案进行搜索要快得多,但需要注意。

解决方案1

假设我想查找系统文件libname-server-2.a,但不想搜索rsnapshot备份。要快速查找系统文件,请使用排除路径/mnt(即,使用/mnt,而不是/mnt/,或/mnt/Backups,或…):

## As sudo (#), to avoid numerous "Permission denied" warnings:

time find / -path /mnt -prune -o -name "*libname-server-2.a*" -print
/usr/lib/libname-server-2.a
real    0m8.644s              ## 8.6 sec  <<< NOTE!
user    0m1.669s
 sys    0m2.466s

## As regular user (victoria); I also use an alternate timing mechanism, as
## here I am using 2>/dev/null to suppress "Permission denied" warnings:

$ START="$(date +"%s")" && find 2>/dev/null / -path /mnt -prune -o \
    -name "*libname-server-2.a*" -print; END="$(date +"%s")"; \
    TIME="$((END - START))"; printf 'find command took %s sec\n' "$TIME"
/usr/lib/libname-server-2.a
find command took 3 sec     ## ~3 sec  <<< NOTE!

…在几秒钟内找到该文件,而这需要更长的时间(似乎在所有“排除”目录中重复出现):

## As sudo (#), to avoid numerous "Permission denied" warnings:

time find / -path /mnt/ -prune -o -name "*libname-server-2.a*" -print
find: warning: -path /mnt/ will not match anything because it ends with /.
/usr/lib/libname-server-2.a
real    33m10.658s            ## 33 min 11 sec (~231-663x slower!)
user    1m43.142s
 sys    2m22.666s

## As regular user (victoria); I also use an alternate timing mechanism, as
## here I am using 2>/dev/null to suppress "Permission denied" warnings:

$ START="$(date +"%s")" && find 2>/dev/null / -path /mnt/ -prune -o \
    -name "*libname-server-2.a*" -print; END="$(date +"%s")"; \
    TIME="$((END - START))"; printf 'find command took %s sec\n' "$TIME"
/usr/lib/libname-server-2.a
find command took 1775 sec    ## 29.6 min

解决方案2

本线程中提供的其他解决方案(SO#4210042)也表现不佳:

## As sudo (#), to avoid numerous "Permission denied" warnings:

time find / -name "*libname-server-2.a*" -not -path "/mnt"
/usr/lib/libname-server-2.a
real    33m37.911s            ## 33 min 38 sec (~235x slower)
user    1m45.134s
 sys    2m31.846s

time find / -name "*libname-server-2.a*" -not -path "/mnt/*"
/usr/lib/libname-server-2.a
real    33m11.208s            ## 33 min 11 sec
user    1m22.185s
 sys    2m29.962s

总结|结论

使用“解决方案1”中所示的方法

find / -path /mnt -prune -o -name "*libname-server-2.a*" -print

... -path <excluded_path> -prune -o ...

请注意,每当您将尾随/添加到排除路径时,find命令就会递归地输入(所有这些)/mnt/*目录——在我的情况下,由于/mnt/Backups/rsnapshot_Backups/*子目录,该目录还包含约2.9 TB的文件要搜索!通过不附加尾随/,搜索应该几乎立即完成(几秒钟内)。

“解决方案2”(…-not-path<exclude-path>…)似乎同样递归地搜索排除的目录——不返回排除的匹配项,但不必要地消耗搜索时间。


在这些rsnapshot备份中搜索:

要在每小时/每天/每周/每月的rsnapshot备份中查找文件,请执行以下操作:

$ START="$(date +"%s")" && find 2>/dev/null /mnt/Backups/rsnapshot_backups/daily.0 -name '*04t8ugijrlkj.jpg'; END="$(date +"%s")"; TIME="$((END - START))"; printf 'find command took %s sec\n' "$TIME"
/mnt/Backups/rsnapshot_backups/daily.0/snapshot_root/mnt/Vancouver/temp/04t8ugijrlkj.jpg
find command took 312 sec   ## 5.2 minutes: despite apparent rsnapshot size
                            ## (~4 GB), it is in fact searching through ~2.9 TB)

排除嵌套目录:

在这里,我想排除嵌套目录,例如,当从/mnt/VVancouver/projects/ie/calls/data/*搜索/mnt/Vvancouver/products/时

$ time find . -iname '*test_file*'
./ie/claws/data/test_file
./ie/claws/test_file
0:01.97

$ time find . -path '*/data' -prune -o -iname '*test_file*' -print
./ie/claws/test_file
0:00.07

旁白:在命令末尾添加-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

其他回答

一个选项是使用grep排除包含目录名的所有结果。例如:

find . -name '*.js' | grep -v excludeddir

对于工作解决方案(在Ubuntu 12.04(精确穿山甲)上测试)。。。

find ! -path "dir1" -iname "*.mp3"

将在当前文件夹和子文件夹(dir1子文件夹除外)中搜索MP3文件。

Use:

find ! -path "dir1" ! -path "dir2" -iname "*.mp3"

…排除dir1和dir2

有很多好的答案,我只是花了一些时间来理解命令的每个元素是什么以及背后的逻辑。

find . -path ./misc -prune -o -name '*.txt' -print

find将开始查找当前目录中的文件和目录,因此查找。。

-o选项代表逻辑OR,并将命令的两部分分开:

[ -path ./misc -prune ] OR [ -name '*.txt' -print ]

不是的任何目录或文件/misc目录不会通过第一个测试路径/其他。但他们将根据第二个表达式进行测试。如果它们的名称与模式*.txt相对应,则会因为-print选项而被打印。

当find到达时/misc目录,此目录仅满足第一个表达式。因此,将对其应用-prune选项。它告诉find命令不要浏览该目录。中的任何文件或目录/find甚至不会探索misc,不会针对表达式的第二部分进行测试,也不会打印。

您可以使用修剪选项来实现这一点。例如:

find ./ -path ./beta/* -prune -o -iname example.com -print

或者反向grep“grep-v”选项:

find -iname example.com | grep -v beta

您可以在Linux find命令exclude directories from search中找到详细的说明和示例。

find -name '*.js' -not -path './node_modules/*' -not -path './vendor/*'

似乎与

find -name '*.js' -not \( -path './node_modules/*' -o -path './vendor/*' \)

并且更容易记住IMO。