使用“查找”时如何排除目录?

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

find . -name '*.js'
1527234 次浏览

使用-prune主键。例如,如果您想排除./misc

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

若要排除多个目录,请在括号之间进行OR。

find . -type d \( -path ./dir1 -o -path ./dir2 -o -path ./dir3 \) -prune -o -name '*.txt' -print

并且,要排除任何级别具有特定名称的目录,请使用-name主目录而不是-path

find . -type d -name node_modules -prune -o -name '*.json' -print
find . -name '*.js' -\! -name 'glob-for-excluded-dir' -prune

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

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

使用-prune选项。所以,类似于:

find . -type d -name proc -prune -o -name '*.js'

'-type d-name proc-prune'仅查找要排除的名为proc的目录。
'-o'是一个'OR'运算符。

我更喜欢-not符号……它更易读:

find . -name '*.js' -and -not -path directory

如果-prune不适合你,这将:

find -name "*.js" -not -path "./directory/*"

警告:需要遍历所有不需要的目录。

我发现以下比其他建议的解决方案更容易推理:

find build -not \( -path build/external -prune \) -name \*.js# you can also exclude multiple pathsfind build -not \( -path build/external -prune \) -not \( -path build/blog -prune \) -name \*.js

重要提示:您在-path之后键入的路径必须与find在没有排除的情况下打印的路径完全匹配。如果这句话混淆了您,请确保在整个命令中使用完整的路径,如下所示:find /full/path/ -not \( -path /full/path/exclude/this -prune \) ...。如果您想更好地理解,请参阅注释[1]。

\(\)内部是一个将匹配完全build/external的表达式(参见上面的重要注释),并将在成功时匹配避免穿越下面的任何东西。然后将其分组为带有转义括号的单个表达式,并以-not为前缀,这将使find跳过与该表达式匹配的任何内容。

有人可能会问,添加-not是否会使-prune隐藏的所有其他文件重新出现,答案是否定的。-prune的工作方式是,一旦到达,该目录下的文件将被永久忽略。

这来自一个实际的用例,我需要在wintersmith生成的一些文件上调用yui-压缩器,但忽略了其他需要按原样发送的文件。


注[1]:如果您想排除/tmp/foo/bar并且像这样运行查找“find /tmp \(...”,那么您必须指定-path /tmp/foo/bar。另一方面,如果您像这样运行查找cd /tmp; find . \(...,那么您必须指定-path ./foo/bar

我使用findxgettext提供文件列表,并希望省略特定目录及其内容。我尝试了-path-prune的许多排列,但无法完全排除我想要删除的目录。

虽然我能够忽略我想要忽略的目录的内容,但find随后将目录本身作为结果之一返回,这导致xgettext崩溃(不接受目录;只有文件)。

我的解决方案是简单地使用grep -v来跳过我在结果中不想要的目录:

find /project/directory -iname '*.php' -or -iname '*.phtml' | grep -iv '/some/directory' | xargs xgettext

无论是否有一个参数find将工作100%,我不能肯定地说。使用grep是一个快速和简单的解决方案后,一些头痛。

以前的答案在Ubuntu上都不好。试试这个:

find . ! -path "*/test/*" -type f -name "*.js" ! -name "*-min-*" ! -name "*console*"

我找到了这个这里

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

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

将在当前文件夹和子文件夹中搜索MP3文件,但在迪尔1子文件夹中除外。

用途:

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

…排除迪尔1和迪尔2

要排除多个目录:

find . -name '*.js' -not \( -path "./dir1" -o -path "./dir2/*" \)

要添加目录,请添加-o -path "./dirname/*"

find . -name '*.js' -not \( -path "./dir1" -o -path "./dir2/*" -o -path "./dir3/*"\)

但如果有许多目录要排除,也许您应该使用正则表达式

对于跳过目录的首选语法应该是什么,这里显然存在一些混淆。

GNU意见

To ignore a directory and the files under it, use -prune

从GNU查找手册页

推理

-prune阻止find降级到目录。只需指定-not -path仍将降级到跳过目录,但当find测试每个文件时,-not -path将为false。

问题-prune

-prune做了它想要做的事情,但在使用它时仍然需要注意一些事情。

  1. #0打印修剪后的目录。

    • TRUE这是预期的行为,它只是没有下降到它。为了避免完全打印目录,请使用逻辑上省略它的语法。
  2. #0仅适用于#1,没有其他操作。

    • 为什么它不适用于删除?对于-delete工作,查找需要按DFS顺序遍历目录,因为-delete将首先删除叶子,然后是叶子的父级,等等……但是为了指定-prune有意义,find需要命中一个目录并停止降序,这显然对-depth-delete没有意义。

性能

我对这个问题的三个最高投票答案进行了简单的测试(将-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

结论

f10bit的语法Daniel C. Sobral的语法平均运行时间为10-25ms。GetFree的语法不使用-prune,需要865ms。所以,是的,这是一个相当极端的例子,但是如果你关心运行时间并且正在做任何远程密集的事情,你应该使用-prune

注意Daniel C. Sobral的语法在两个-prune语法中表现得更好;但是,我强烈怀疑这是一些缓存的结果,因为切换两个运行的顺序会导致相反的结果,而非修剪版本总是最慢的。

测试脚本

#!/bin/bash
dir='.performance_test'
setup() {mkdir "$dir" || exit 1mkdir -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"/*; doif [[ -d "$file" ]]; thencount=$(find "$file" | wc -l)printf "%-30s %-10s\n" "$file" "$count"fidone}
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"setupecho "----------------------------------------------"echo "# of files/dirs in level one directories"stats | sort -k 2 -n -recho "----------------------------------------------"
printf "\nRunning performance test...\n\n"
echo \> find \""$dir"\" -path \""$dir/prune_me"\" -prune -o -exec bash -c \'echo \"\$0\"\'  {} \\\;name1s=$(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\"\' {} \\\;name2s=$(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\"\' {} \\\;name3s=$(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' -not -path './node_modules/*' -not -path './vendor/*'

似乎工作原理与

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

更容易记住IMO。

这是有效的,因为find测试模式*foo*”的文件:

find ! -path "dir1" ! -path "dir2" -name "*foo*"

但是,如果您不使用模式find不会测试文件),它会不是工作。因此find不使用其先前评估的“真正”和“虚假”布尔值。使用上述表示法不工作的用例示例:

find ! -path "dir1" ! -path "dir2" -type f

没有find测试!因此,如果您需要查找没有任何模式匹配的文件,请使用-prune。此外,通过使用prunefind总是更快,而它确实跳过了该目录,而不是匹配它或更好地不匹配它。所以在这种情况下,请使用如下内容:

find dir -not \( -path "dir1" -prune \) -not \( -path "dir2" -prune \) -type f

或:

find dir -not \( -path "dir1" -o -path "dir2" -prune \) -type f

问候

如何使用-修剪-选择-查找-in-shLaurence 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对中。

pushd /path/to/search;                  \find .                                  \-type d                               \\( -path ./exclude_me               \-o                               \-name exclude_me_too_anywhere    \\)                                 \-prune                              \-o                                    \-type f -name '*\.js' -print;         \popd

这是适合我在Mac上:

find . -name *.php -or -path "./vendor" -prune -or -path "./app/cache" -prune

它将排除后缀为php的搜索名称的vendorapp/cache目录。

我在C源文件中找到了函数名称,使用此命令排除*. o和排除*. swp和排除(不是常规文件)并排除dir输出:

find .  \( ! -path "./output/*" \) -a \( -type f \) -a \( ! -name '*.o' \) -a \( ! -name '*.swp' \) | xargs grep -n soc_attach

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

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

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

find -iname example.com | grep -v beta

您可以在Linux查找命令从搜索中排除目录中找到详细的说明和示例。

最好使用exec操作而不是for循环:

find . -path "./dirtoexclude" -prune \-o -exec java -jar config/yuicompressor-2.4.2.jar --type js '{}' -o '{}' \;

exec ... '{}' ... '{}' \;将对每个匹配的文件执行一次,将大括号'{}'替换为当前文件名。

请注意,大括号用单引号括起来,以保护它们不被解释为外壳脚本标点符号*


备注

*来自find (GNU findutils) 4.4.2手册页的示例部分

对于FreeBSD用户:

 find . -name '*.js' -not -path '*exclude/this/dir*'

这是我用来排除一些路径的格式:

$ find ./ -type f -name "pattern" ! -path "excluded path" ! -path "excluded path"

我用它来查找不在“.*”路径中的所有文件:

$ find ./ -type f -name "*" ! -path "./.*" ! -path "./*/.*"

如果搜索目录有模式(在我的情况下,大多数时候);你可以简单地像下面这样做:

find ./n* -name "*.tcl"

在上面的例子中;它搜索以“n”开头的所有子目录。

我发现此页面上的建议和许多其他页面在我的Mac OS X系统上不起作用。但是,我发现了一个对我有效的变体。

最大的想法是搜索MacintoshHD但避免遍历所有外部卷,这些卷主要是Time Machine备份,映像备份,挂载的共享和存档,但不必将它们全部卸载,这通常是不切实际的。

这是我的工作脚本,我将其命名为“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 volumesdateecho Enter sudo password if requestedsudo 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" -printdateecho ============================iMac2:~ jas$

各种路径与外部存档卷、Time Machine、虚拟机、其他挂载的服务器等有关。一些卷名称中包含空格。

一个好的测试运行是“finditindex.php”,因为该文件出现在我的系统上的许多地方。使用此脚本,搜索主硬盘大约需要10分钟。如果没有这些排除,则需要很多小时。

我想知道目录的数量,文件的MB只是当前目录-代码正是我想要的:-)

的来源

- ...    2791037 Jun  2  2011 foo.jpg- ... 1284734651 Mär 10 16:16 foo.tar.gz- ...          0 Mär 10 15:28 foo.txtd ...       4096 Mär  3 17:12 HEd ...       4096 Mär  3 17:21 KUd ...       4096 Mär  3 17:17 LEd ...          0 Mär  3 17:14 NOd ...          0 Mär  3 17:15 SEd ...          0 Mär  3 17:13 SPd ...          0 Mär  3 17:14 TEd ...          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}'

注意:额外的format="%s%'12d\n"awk格式化数字所必需的。

的结果

Anzahl Ordner  =            8Anzahl Dateien =            3Groesse (MB)   =        1.228

不确定这是否会涵盖所有边缘情况,但以下内容将非常直接且易于尝试:

ls -1|grep -v -e ddl -e docs| xargs rm -rf

这应该从当前目录中删除所有文件/目录,不包括“ddls”和“docs”。

我尝试了上面的命令,但没有一个使用“-prune”的人适合我。最后我用下面的命令尝试了这个:

find . \( -name "*" \) -prune -a ! -name "directory"

-path-prune方法也适用于路径中的通配符。这是一个查找语句,它将查找为多个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-不的旧版本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

-prune绝对有效,是最好的答案,因为它可以防止下降到要排除的目录。-not -path仍然搜索排除的目录,它只是不打印结果,如果排除的目录是挂载的网络卷或您没有权限,这可能是一个问题。

棘手的部分是find对参数的顺序非常挑剔,所以如果你没有让它们恰到好处,你的命令可能无法工作。参数的顺序通常是这样的:

find {path} {options} {action}

{path}:首先放置所有与路径相关的参数,如. -path './dir1' -prune -o

{options}:当把-name, -iname, etc作为这个组的最后一个选项时,我取得了最大的成功。例如-type f -iname '*.js'

{action}:使用-prune时需要添加-print

下面是一个工作示例:

# setup testmkdir dir1 dir2 dir3touch dir1/file.txt; touch dir1/file.jstouch dir2/file.txt; touch dir2/file.jstouch dir3/file.txt; touch dir3/file.js
# search for *.js, exclude dir1find . -path './dir1' -prune -o -type f -iname '*.js' -print
# search for *.js, exclude dir1 and dir2find . \( -path './dir1' -o -path './dir2' \) -prune -o -type f -iname '*.js' -print

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

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

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

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

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

./misc目录中没有的任何目录或文件都不会通过第一个测试-path ./misc。但它们将针对第二个表达式进行测试。如果它们的名称与模式*.txt对应,则由于-print选项,它们会被打印出来。

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

这是唯一一个为我工作。

find / -name MyFile ! -path '*/Directory/*'

搜索“MyFile”,不包括“Directory”。#36825;星的影响

对于我需要的东西,它是这样工作的,从root开始在所有服务器中查找landscape.jpg,并排除在/var目录中的搜索:

find / -maxdepth 1 -type d | grep -v /var | xargs -I '{}' find '{}' -name landscape.jpg

find / -maxdepth 1 -type d列出了/中的所有d个目录

grep -v /var从列表中排除'/var'

xargs -I '{}' find '{}' -name landscape.jpg对列表中的每个目录/结果执行任何命令,如find

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

示例:

find / -path /mnt -prune -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 -l60314138    ## 60.3M files, folders34:07.30    ## 34 min
time du /mnt/Backups/rsnapshot_backups -d 03112240160  /mnt/Backups/rsnapshot_backups    ## 3.1 TB33:51.88    ## 34 min
time rsnapshot du    ## << more accurate re: rsnapshot footprint2.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

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


示例

在这个线程(如何排除查找中的目录。命令)中提出的各种方法中,我发现使用已接受答案的搜索速度更快-有警告。

解决方案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.areal    0m8.644s              ## 8.6 sec  <<< NOTE!user    0m1.669ssys    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.afind 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*" -printfind: warning: -path /mnt/ will not match anything because it ends with /./usr/lib/libname-server-2.areal    33m10.658s            ## 33 min 11 sec (~231-663x slower!)user    1m43.142ssys    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.afind 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.areal    33m37.911s            ## 33 min 38 sec (~235x slower)user    1m45.134ssys    2m31.846s
time find / -name "*libname-server-2.a*" -not -path "/mnt/*"/usr/lib/libname-server-2.areal    33m11.208s            ## 33 min 11 secuser    1m22.185ssys    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.jpgfind command took 312 sec   ## 5.2 minutes: despite apparent rsnapshot size## (~4 GB), it is in fact searching through ~2.9 TB)

不包括嵌套目录:

在这里,我想排除嵌套目录,例如从/mnt/Vancouver/projects/搜索时的/mnt/Vancouver/projects/ie/claws/data/*

$ time find . -iname '*test_file*'./ie/claws/data/test_file./ie/claws/test_file0:01.97
$ time find . -path '*/data' -prune -o -iname '*test_file*' -print./ie/claws/test_file0: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

而不是:

for file in $(find . -name '*.js')dojava -jar config/yuicompressor-2.4.2.jar --type js $file -o $filedone

…并且由于您没有定义要排除的子目录,因此可以使用:

for file in $(find *.js -maxdepth 0 -name '*.js')dojava -jar config/yuicompressor-2.4.2.jar --type js $file -o $filedone

此语法将排除所有子目录。

请看下面的例子:在我的tmp目录下,我有一个巨大的“存档”子目录,其中包含17000-4640=12360个文件。这个目录位于一个缓慢的NFS上。虽然第一种语法扫描“存档”子目录并执行得很差,但第二种语法只扫描我当前目录中包含的“*pdf”文件并执行……还不错。

[tmp]$ time (find . -name "*pdf" | wc -l)17000
real    0m40.479suser    0m0.423ssys     0m5.606s
[tmp]$ time (find *pdf -maxdepth 0 -name "*pdf" | wc -l)4640
real    0m7.778suser    0m0.113ssys     0m1.136s

第二种语法非常有趣:在下面的示例中,我想检查文件or60runm50958.pdf是否存在并且超过20分钟。亲自看看第二种语法如何更有效。这是因为它避免了扫描存档子目录。

[tmp]$ time find . -name or60runm50958.pdf -mmin +20./or60runm50958.pdf
real    0m51.145suser    0m0.529ssys     0m6.243s
[tmp]$ time find or60runm50958.pdf -maxdepth 0 -name or60runm50958.pdf -mmin +20or60runm50958.pdf
real    0m0.004suser    0m0.000ssys     0m0.002s

避免打印修剪目录的一个好技巧是在-prune之后的-or右侧之后使用-print(也适用于-exec)。例如,…

find . -path "*/.*" -prune -or -iname "*.j2"

将打印当前目录下所有文件的路径,扩展名为“. j2”,跳过所有隐藏目录。整齐。但它也会打印跳过的每个目录的完整路径,如上所述。然而,以下并没有,…

find . -path "*/.*" -prune -or -iname "*.j2" -print

因为从逻辑上讲,在-iname运算符之后和-print之前有一个隐藏的-and。由于布尔运算顺序和结合性,这将它绑定到-or子句的右侧。但是文档说,如果它(或它的任何表兄弟…-print0等)没有指定,就会有一个隐藏的-print。那么为什么不是-or打印的左侧部分呢?显然(我从第一次阅读手册页时不明白这一点),如果没有-print-或-exec ANYWHERE,这是真的,在这种情况下,-print在逻辑上被分散在周围,这样所有东西都被打印出来。如果甚至ONEprint风格的操作在任何子句中表达,所有那些隐藏的逻辑操作都会消失,你只得到你指定的东西。坦率地说,我可能更喜欢反过来,但是只有描述性运算符的find显然什么也做不了,所以我想这是有道理的。如上所述,这一切也适用于-exec,因此以下给出了每个具有所需扩展名的文件的完整-iname1列表,但没有列出每个隐藏目录的第一层,…

find . -path "*/.*" -prune -or -iname "*.j2" -exec ls -la -- {} +

对我(和这个线程上的其他人)来说,find语法很快就变得非常巴洛克式,所以我总是加入括号来确保我知道什么绑定到什么,所以我通常为类型能力创建一个宏并形成所有这样的语句…

find . \( \( ... description of stuff to avoid ... \) -prune \) -or \\( ... description of stuff I want to find ... [ -exec or -print] \)

以这种方式将世界分为两部分很难出错。我希望这会有所帮助,尽管似乎不太可能有人读到第30个以上的答案并投赞成票,但人们可以希望。:-)

以下命令工作:

find . -path ./.git -prune -o -print

如果您在查找时遇到问题,请使用-D tree选项查看表达式分析信息。

find -D tree . -path ./.git -prune -o -print

或者-D all,查看所有执行信息。

find -D all . -path ./.git -prune -o -print

您还可以使用正则表达式来包含/排除一些文件 /dirs您的搜索使用这样的东西:

find . -regextype posix-egrep -regex ".*\.(js|vue|s?css|php|html|json)$" -and -not -regex ".*/(node_modules|vendor)/.*"

这只会给你所有的js、vue、css等文件,但不包括node_modulesvendor文件夹中的所有文件。

find . \( -path '.**/.git' -o -path '.**/.hg' \) -prune -o -name '*.js' -print

上面的示例查找当前目录下的所有*.js文件,不包括文件夹.git.hg,无论这些.git.hg文件夹有多深。

注意:这也有效:

find . \( -path '.*/.git' -o -path '.*/.hg' \) -prune -o -name '*.js' -print

但我更喜欢**表示法,因为它与其他一些工具保持一致,这在这里是离题的。

我认为自己是一个bash迷,但是……在过去的2年里,我没有找到一个简单的bash用户友好的解决方案来解决这个问题。通过“用户友好”,我的意思是只需一次调用,这不需要我记住复杂的语法+我可以使用与以前相同的查找语法,所以以下解决方案最适合那些^^^

将此复制粘贴到shell中并获取~/.bash_aliases:

cat << "EOF" >> ~/.bash_aliases# usage: source ~/.bash_aliases , instead of find type findd + rest of syntaxfindd(){dir=$1; shift ;find  $dir -not -path "*/node_modules/*" -not -path "*/build/*" \-not -path "*/.cache/*" -not -path "*/.git/*" -not -path "*/venv/*" $@}EOF

当然,为了添加或删除目录以排除您必须使用您选择的目录编辑此别名func…

#find command in linuxdef : find command used to locate /search files in unix /linux system ,find  search for files in a directory hierarchy
1)exec   Show diagnostic information relating to -exec, -execdir, -ok and -okdir2)-options-H =do not follow symoblic links while except while procesing .-L = follow symbolic links-P =never follow symbolic links
-type cFile is of type c:
b      block (buffered) special
c      character (unbuffered) special
d      directory
p      named pipe (FIFO)
f      regular file
l      symbolic  link;  this  is  never true if the -L option or the -follow option is in effect, unless thesymbolic link is broken.  If you want to search for symbolic links when -L is in effect, use -xtype.
s      socket
D      door (Solaris)
-DeleteDelete files; true if removal succeeded.  If the removal failed, an error message  is  issued.If  -delete#fails, find's exit status will be nonzero (when it eventually exits).

find /home/mohan/a -mindepth 3 -maxdepth 3 -type f -name "*.txt" |xargs rm -rffind -type d -namefind -type f -Namefind /path/ -type f -iname (i is case insenstive)
#find directores a/b/c and only delete c directory inside have "*.txt "find /home/mohan/a -mindepth 3 -maxdepth 3 -type f -name "*.txt" |xargs rm -rffind /home/mohan/a -mindepth 3 -maxdepath 3 -type f -name "*.txt" -delete

#delete particular directory have empty file and only  we can delete empty filesfind /home/mohan -type f -name "*.txt" -empty -DELETE

#find multiple files and also find empty filesfind /home/mohan -type f \( -name "*.sh" -o  -name "*.txt" \) -empty
#delete empty files two or more Filesfind /home/mohan -type f \( -nmae "*.sh" -o -name "*.txt" \) -empty -delete

#How to append contents of multiple files into one filefind . -type f -name '*.txt' -exec cat {} + >> output.file
#last modified files finding using less than 1 min (-n)ls -lrth|find . -type f -mmin -1
#last modified files more than 1 min (+n)ls -lrth|find . -type f -mmin +1

#last modified files exactly one minsfind . -type f -mmin 1
last modifiedfiles exactly in one day by using command (-mtime)find . -type f -mtime 10
#last modified more than 10 daysfind . -type  f -mtime +10
#last modified less than 10 daysfind . -type f -mtime -10
#How to Find Modified Files and Folders Starting from a Given Date to the Latest Datefind . -type f  -newermt "17-11-2020"
#How to Find a List of “sh” Extension Files Accessed in the Last 30 Days--- -matdimtypels -lrt|find . -type f -iname ".sh" -atime -30
#How to Find a List of Files Created Today, -1 means less than min,ls -lrt | find . -type f -ctime -1 -ls

另一个使用多个模式的例子-o -name

在根目录/中搜索所有*.tpl*.tf文件,不包括驻留在/src/.terraform//code/中的文件。

$ find / -type f \( -name '*.tf' -o -name '*.tpl' \) \-and \( -not -path '/src/.terraform/*' -and -not -path '/code/*' \)

/src/debug.tf/src/nodegroup-infra.tpl/src/variables.tf.tpl

我用超精细测试了上面的命令;测试是在一个有3k目录和12k文件的系统上进行的。

Benchmark #1: ./entrypoint.shTime (mean ± σ):      69.2 ms ±   1.4 ms    [User: 22.6 ms, System: 43.6 ms]Range (min … max):    66.4 ms …  72.2 ms    42 runs

目录结构示例

/code/目录树

bash-5.0# tree /code/code├── debug.tf├── entrypoint.sh├── nodegroup-infra.tpl├── tftemplate.sh└── variables.tf.tpl
0 directories, 5 files

/src/目录树

bash-5.0# tree /src/src├── Dockerfile├── debug.tf├── entrypoint.sh├── nodegroup-infra.tpl├── terraform.tfstate├── terraform.tfstate.backup└── variables.tf.tpl
0 directories, 7 files

根节点目录树摘要

$ tree /...3382 directories, 12164 files

如果有人在研究如何一次忽略多个路径。您可以使用bash数组(在GNU bash版本4.4.20(1)-发行版上完美运行)

#!/usr/bin/env bash
# This script helps ignore unnecessary dir paths while using the find command
EXCLUDE_DIRS=("! -path /*.git/*""! -path /*go/*""! -path /*.bundle/*""! -path /*.cache/*""! -path /*.local/*""! -path /*.themes/*""! -path /*.config/*""! -path /*.codeintel/*""! -path /*python2.7/*""! -path /*python3.6/*""! -path /*__pycache__/*")find $HOME -type f ${EXCLUDE_DIRS[@]}
# if you like fzf
find $HOME -type f ${EXCLUDE_DIRS[@]} | fzf --height 40% --reverse

此外,由于某种原因,您将无法忽略 /bin/目录路径。

您也可以使用

find  -type f -not -name .directoryname -printf "%f\n"

在LinuxUbuntu 18.04和20.04中测试。

find非常重要和强大,但是它是如此微妙和令人困惑!

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

快速总结与解答:

遵循这些模式。另见我的评论在这里。这些是我发现的最好和最有效的模式,句号。转义括号(\(\))和-prune选项对速度很重要。阅读下面找出原因。

使用的最佳模式:

删除下面每个命令的-name '*.js'部分,当然,如果你正在寻找一个通用的答案,而不是试图解决OP的原始问题,这也涉及只找到扩展名为.js的文件。

# Exclude one path, and its contents, saving time by *not* recursing down the# excluded path at all.find . -name '*.js' -not \( -path "./dir_to_exclude" -prune \)
# Add the wildcard asterisk (`*`) to the end of the match pattern, as# in "./dir_to_exclude*", to exclude all files & folders beginning with the# name `./dir_to_exclude`. Prune to save time by *not* recursing down the# excluded paths at all.# - You can add the asterisk to the end of the pattern to apply this pattern to#   all examples below as well, if desired.# - This example pattern would exclude "./dir_to_exclude", "./dir_to_exclude1",#   "./dir_to_exclude2", "./dir_to_exclude99", "./dir_to_exclude_some_long_name",#   "./dir_to_exclude_another_long_name", etc., as well as exclude all **files**#   beginning with this match pattern but not otherwise in an excluded dir.find . -name '*.js' -not \( -path "./dir_to_exclude*" -prune \)
# Exclude multiple paths and their contents, saving time by *not* recursing down# the excluded paths at all.find . -name '*.js' \-not \( -path "./dir_to_exclude1" -prune \) \-not \( -path "./dir_to_exclude2" -prune \) \-not \( -path "./dir_to_exclude3" -prune \)

# If you change your "starting point" path from `.` to something else, be sure# to update the beginning of your `-path` with that as well, like this:
find "some_dir" -name '*.js' -not \( -path "some_dir/dir_to_exclude" -prune \)
find "some_dir" -name '*.js' \-not \( -path "some_dir/dir_to_exclude1" -prune \) \-not \( -path "some_dir/dir_to_exclude2" -prune \) \-not \( -path "some_dir/dir_to_exclude3" -prune \)

上面的模式是最好的,因为当-prune选项打开时,转义括号如上所示,当您指定这样的文件夹名称时(在这种情况下,文件夹名称之后没有任何内容),它会排除文件夹的内容。

如果您删除括号和-prune选项,-not -path "./dir_to_exclude"将不希望排除只有的目录名,但没有的内容。如果您不遵循我上面推荐的模式,您必须使用-not -path "./dir_to_exclude"仅排除文件夹姓名,和-not -path "./dir_to_exclude/*"仅排除文件夹内容,和-not -path "./dir_to_exclude" -not -path "./dir_to_exclude/*"排除两者

此外,从我上面的示例中删除括号和-prune选项需要长2x~100x。这是巨大的速度差异!使用括号和-prune选项会导致find不会递归排除的目录,而find . -not -path "./dir_to_exclude" -not -path "./dir_to_exclude/*"仍然会浪费大量时间递归排除的目录。

讨论细微差别和经验法则

使用find时:

  1. 您必须在要匹配的-path中包含通配符(*)或“起点”路径。例子:

    1. 通过前缀-path以匹配“起点”路径来匹配相对于“起点”路径的确切路径:

      # 1. with the "starting point" being the current directory, `.`find . -not -path "./dir_to_exclude/*"# or (same thing)find -not -path "./dir_to_exclude/*"
      # 2. with the "starting point" being the root dir, `/`find / -not -path "/dir_to_exclude/*"
      # 3. with the "starting point" being "some_dir"find "some_dir" -not -path "some_dir/dir_to_exclude/*"

      同样,请注意,在上面的所有-path匹配中,您必须显式地在路径前缀“起点”路径。否则,您可以使用通配符:

    2. 匹配通配符路径以在搜索路径中的任何级别或子目录处找到您的-path。即:用*前缀您的-path。例子:

      # match "./dir_to_exclude/file1" as well as#       "./another_dir/dir_to_exclude/file1"find . -not -path "*/dir_to_exclude/*"
      # match "/dir_to_exclude/file1" as well as#       "/another_dir/dir_to_exclude/file1"find / -not -path "*/dir_to_exclude/*"
      # match "some_dir/dir_to_exclude/file1" as well as#       "some_dir/another_dir/dir_to_exclude/file1"find "some_dir" -not -path "*/dir_to_exclude/*"

      同样,请注意,在上面的所有-path匹配中,我明确地用*通配符字符作为路径前缀,以便在任何级别进行匹配。

  2. 使用-ipath进行case麻木不仁路径匹配。从man find

    -ipath patternLike -path.  but the match is case insensitive.

    示例:

    # exclude "./dir_to_exclude/*", as well as "./DIR_TO_EXCLUDE/*", and# "./DiR_To_eXcluDe/*", etc.find . -not -ipath "./dir_to_exclude/*"
  3. 没有使用转义括号和-prune选项时,find仍然会递归排除的路径,使其像泥浆一样慢。☹️

  4. 没有使用转义括号和-prune选项时,find . -not -path "./dir_to_exclude/*"仅排除了被排除的目录的内容,但不排除被排除的目录本身,find . -not -path "./dir_to_exclude"仅排除了目录名称本身,但不排除该目录中的内容(文件和文件夹)!使用两者来排除两者。例子:

    # exclude the files and folders within the excluded dir, but# leaving "./dir_to_exclude" itselffind . -not -path "./dir_to_exclude/*"
    # exclude the dir name only, but leaving (NOT excluding) all files and# folders within that dir!find . -not -path "./dir_to_exclude"
    # exclude both the folder itself, as well as its contentsfind . \-not -path "./dir_to_exclude/*" \-not -path "./dir_to_exclude"
  5. 这个经验法则部分中的所有上述示例都是纯粹的垃圾🧻和垃圾🗑☹️。我开玩笑和夸大其词,但关键是:我认为它们并没有那么好,原因已经解释过了。你应该用转义括号和-prune选项包装它们中的每一个,像这样😀:

    find .          -not \( -path "./dir_to_exclude/*" -prune \)find            -not \( -path "./dir_to_exclude/*" -prune \)find /          -not \( -path "/dir_to_exclude/*" -prune \)find "some_dir" -not \( -path "some_dir/dir_to_exclude/*" -prune \)
    find .          -not \( -path "*/dir_to_exclude/*" -prune \)find /          -not \( -path "*/dir_to_exclude/*" -prune \)find "some_dir" -not \( -path "*/dir_to_exclude/*" -prune \)
    find .          -not \( -ipath "./dir_to_exclude/*" -prune \)
    find .          -not \( -path "./dir_to_exclude/*" -prune \)find .          -not \( -path "./dir_to_exclude" -prune \)find . \-not \( -path "./dir_to_exclude/*" -prune \) \-not \( -path "./dir_to_exclude" -prune \)

以上内容是我截至2022年9月4日的最新信息。下面的内容是我的老答案,它仍然有大量有用的信息,但是没有涵盖我上面介绍的那些细微差别。阅读它以获得更多的知识,并查看更多的例子,将你上面学到的东西应用到我下面介绍的中。

通用示例

请注意,./(或*/,见下文)之前/*(或*,但请参阅下面的警告)之后要排除的文件夹名称是选填/必填,以便排除dir_to_exclude,以及其中的任何内容!

此外,对速度没有遍历排除目录,请注意真正重要的转义分组括号和-prune选项。例如:find -not \( -path "*/dir_to_exclude/*" -prune \)

要在手册页中查看这些转义分组括号的示例,请运行man find,然后按//进行搜索。搜索模式\(,例如,使用正则表达式模式\\\(。按输入开始搜索手册页。搜索时按N进行“下一个匹配”。

总结

这些工作:

# [my favorite #1] exclude contents of `dir_to_exclude` at the search rootfind -not -path "./dir_to_exclude/*"
# exclude all files & folders beginning with the name `dir_to_exclude` at the# search rootfind -not -path "./dir_to_exclude*"
# [my favorite #2] exclude contents of `dir_to_exclude` at any level within your# search pathfind -not -path "*/dir_to_exclude/*"
# exclude all files & folders beginning with the name `dir_to_exclude` at any# level within your search pathfind -not -path "*/dir_to_exclude*"
# To exclude multiple matching patterns, use `-not -path "*/matching pattern/*"`# multiple times, like thisfind -not -path "*/dir_to_exclude1/*" -not -path "*/dir_to_exclude2/*"

[使用这些]这些也有效,并且更好,因为它们导致查找不必要地遍历排除的路径!:
(这使得速度相差巨大(快2倍~100倍)!参见这里这里。您还可以分别使用转义搜索字符串\\\(\\\)man find页面本地搜索字符串\(\)

find -not \( -path "./dir_to_exclude" -prune \)  # works to exclude *both* the# directory *and* its contents# here, here but does *not*# exclude the contents as well# when the directory name is# written like this in the# examples abovefind -not \( -path "./dir_to_exclude*" -prune \)find -not \( -path "./dir_to_exclude/*" -prune \)find -not \( -path "*/dir_to_exclude" -prune \)  # same note as just abovefind -not \( -path "*/dir_to_exclude*" -prune \)find -not \( -path "*/dir_to_exclude/*" -prune \)
# To exclude multiple matching patterns at once, use the `-not \( ... \)`# pattern multiple times, like thisfind -not \( -path "*/dir_to_exclude1/*" -prune \) \-not \( -path "*/dir_to_exclude2/*" -prune \)

但这些都不起作用:

# These do NOT work!find -not -path "dir_to_exclude"find -not -path "dir_to_exclude/*"find -not -path "./dir_to_exclude"find -not -path "./dir_to_exclude/"

关键是,通常,要使其工作,您必须以#0或#1开始每个匹配模式,并以#2或#3结束每个匹配模式,这取决于您要实现的目标。我说“一般”,因为在上面的-not \( ... \)样式部分中有两个注意到的例外。您可以通过它们右侧的注释来识别这两个例外:# works here but not above

进一步解释:

  1. [最佳,取决于您想要的]这有效!排除您正在搜索的根目录中dir_to_exclude内的所有文件和文件夹。请注意,这排除了dir_to_exclude中的所有子文件和子文件夹,但它不排除dir_to_exclude目录本身。
    find -not \( -path "./dir_to_exclude/*" -prune \)
  2. 还排除dir_to_exclude目录本身(以及名称以这些字符开头的任何文件或文件夹)。警告:这也排除了dir_to_exclude1dir_to_exclude2dir_to_exclude_anyTextHere等。它排除了任何仅以文本dir_to_exclude开头并位于您正在搜索的根目录中的文件或文件夹。
    find -not \( -path "./dir_to_exclude*" -prune \)
  3. [最好,取决于你想要什么]递归在搜索路径的任何级别排除此名称的目录。只需在路径的前面添加通配符*,而不是使用.来指示搜索根目录。
    find -not \( -path "*/dir_to_exclude/*" -prune \)
  4. 递归排除名称它始于和字符dir_to_exclude在您的搜索路径中的任何级别的任何文件或文件夹。(另请参阅上面的警告)。
    find -not \( -path "*/dir_to_exclude*" -prune \)

总结:

./中,开头的.表示“从当前目录开始”(或者在*/中,*是一个通配符,用于拾取到此点的任何字符),在/*的末尾,*是一个通配符,用于拾取/字符之后的路径字符串中的任何字符。这意味着以下内容:

  1. "./dir_to_exclude/*"匹配根搜索目录(./)中dir_to_exclude中的所有子文件和子文件夹,但不匹配目录本身。
  2. "./dir_to_exclude*"匹配根搜索目录(./)中的所有文件和文件夹,包括dir_to_exclude,以及其中的所有内容,但还有一个警告它将匹配以字符dir_to_exclude开头的任何文件或文件夹名称。
  3. "*/dir_to_exclude/*"匹配搜索路径中任何级别的任何目录*/)中dir_to_exclude中的所有子文件和子文件夹,但不匹配目录本身。
  4. "*/dir_to_exclude*"匹配以dir_to_exclude开头的名称在搜索路径中的任何级别(#1)的所有文件和文件夹。

走得更远

从那里,我喜欢管道到grep以在感兴趣的路径中搜索某些匹配的模式。例如:搜索不在dir_to_exclude目录内并且其中包含desired_file_name.txt的任何路径:

# Case-sensitive; notice I use `\.` instead of `.` when grepping, in order to# search for the literal period (`.`) instead of the regular expression# wildcard char, which is also a period (`.`).find -not \( -path "./dir_to_exclude/*" -prune \) \| grep "desired_file_name\.txt"
# Case-INsensitive (use `-i` with your `grep` search)find -not \( -path "./dir_to_exclude/*" -prune \) \| grep -i "desired_file_name\.txt"
# To make `dir_to_exclude` also case INsensitive, use the `find` `-ipath` option# instead of `-path`:find -not -ipath \( -path "./dir_to_exclude/*" -prune \) \| grep -i "desired_file_name\.txt"

排除多个匹配模式,只需多次使用-not \( -path "*/matching pattern/*" -prune \)。例如:

# Exclude all ".git" and "..git" dirs at any level in your search pathfind -not \( -path "*/.git/*" -prune \) -not \( -path "*/..git/*" -prune \)

我将上述示例用作我的#0别名的一部分(更新:该别名正在扩展并移动到sublf.sh脚本在这个文件夹里中)。此别名允许我使用fzf模糊查找器快速搜索并打开Sublime Text中的多个文件。有关最新版本,请参阅上面的链接。

alias sublf='FILES_SELECTED="$(find -not \( -path "*/.git/*" -prune \) \-not \( -path "*/..git/*" -prune \) \| fzf -m)" \&& echo "Opening these files in Sublime Text:" \&& echo "$FILES_SELECTED" \&& subl $(echo "$FILES_SELECTED")'

参考文献:

  1. 【本题主要答案】使用“查找”时如何排除目录?
  2. https://unix.stackexchange.com/questions/350085/is-it-possible-to-exclude-a-directory-from-the-find-command/350172#350172
  3. https://unix.stackexchange.com/questions/32155/find-command-how-to-ignore-case/32158#32158

另见:

  1. [我还需要学习和阅读这个]https://www.baeldung.com/linux/find-exclude-paths
  2. [我的回答]如何将查找(文件的多行字符串列表)的输出存储到bash数组中

关键词:在查找命令中排除dir;不要使用查找搜索路径;不区分大小写的查找和grep命令

如果有人想在Makefile中添加查找命令,这里是我们排除目录的方法

! -path "*/directoryName/*"

下面是格式化所有Go语言文件的示例,不包括原型文件和供应商目录下的所有文件:

find . ! -name '*.pb.go' -name '*.go' ! -path "*/vendor/*" -exec gofmt -s -w '{}' +

如果您正在寻找一个高性能的答案,那么它是:

find . -type d -name node_modules -prune -false -o -type f

使用-false排除node_modules本身。

在node_modules中有10000个文件的目录中,它将比-not -path方法快3倍。

find . -type f -not -path '*node_modules*'

如果node_modules有更多的文件,您将获得更高的性能。