我想查找以 结尾的文件_peaks.bed
,但排除tmp
和scripts
文件夹中的文件。
我的命令是这样的:
find . -type f \( -name "*_peaks.bed" ! -name "*tmp*" ! -name "*scripts*" \)
但它没有用。文件夹中的tmp
文件script
仍将显示。
有人对此有想法吗?
以下是您可以使用以下方式指定的方法find
:
find . -type f -name "*_peaks.bed" ! -path "./tmp/*" ! -path "./scripts/*"
解释:
find .
- 从当前工作目录开始查找(默认递归)-type f
- 指定find
您只希望结果中的文件-name "*_peaks.bed"
- 查找名称以结尾的文件_peaks.bed
! -path "./tmp/*"
- 排除路径以开头的所有结果./tmp/
! -path "./scripts/*"
- 同时排除路径以开头的所有结果./scripts/
测试解决方案:
$ mkdir a b c d e
$ touch a/1 b/2 c/3 d/4 e/5 e/a e/b
$ find . -type f ! -path "./a/*" ! -path "./b/*"
./d/4
./c/3
./e/a
./e/b
./e/5
您非常接近,该-name
选项仅考虑基本名称,其中-path
考虑整个路径=)
这是您可以做到的一种方法...
find . -type f -name "*_peaks.bed" | egrep -v "^(./tmp/|./scripts/)"
利用
find \( -path "./tmp" -o -path "./scripts" \) -prune -o -name "*_peaks.bed" -print
或者
find \( -path "./tmp" -o -path "./scripts" \) -prune -false -o -name "*_peaks.bed"
或者
find \( -path "./tmp" -path "./scripts" \) ! -prune -o -name "*_peaks.bed"
顺序很重要。它从左到右评估。始终从路径排除开始。
不要使用-not
(或!
)排除整个目录。使用-prune
. 如手册中所述:
−prune The primary shall always evaluate as true; it
shall cause find not to descend the current
pathname if it is a directory. If the −depth
primary is specified, the −prune primary shall
have no effect.
并在 GNU 查找手册中:
-path pattern
[...]
To ignore a whole
directory tree, use -prune rather than checking
every file in the tree.
实际上,如果您使用-not -path "./pathname"
, find 将评估 下每个节点的表达式"./pathname"
。
find 表达式只是条件评估。
\( \)
- 分组操作(您可以使用-path "./tmp" -prune -o -path "./scripts" -prune -o
,但它更详细)。-path "./script" -prune
- 如果-path
返回 true 并且是一个目录,则为该目录返回 true 并且不要进入它。-path "./script" ! -prune
- 它评估为(-path "./script") AND (! -prune)
。它将修剪的“始终正确”恢复为始终错误。它避免打印"./script"
作为匹配项。-path "./script" -prune -false
- 因为-prune
总是返回 true,你可以跟随它-false
来做同样的 than !
。-o
- OR 运算符。如果两个表达式之间没有指定运算符,则默认为 AND 运算符。因此,\( -path "./tmp" -o -path "./scripts" \) -prune -o -name "*_peaks.bed" -print
扩展为:
[ (-path "./tmp" OR -path "./script") AND -prune ] OR ( -name "*_peaks.bed" AND print )
打印在这里很重要,因为没有它会扩展到:
{ [ (-path "./tmp" OR -path "./script" ) AND -prune ] OR (-name "*_peaks.bed" ) } AND print
-print
由 find 添加 - 这就是为什么大多数时候,您不需要在表达式中添加它。由于-prune
返回 true,它将打印“./script”和“./tmp”。
在其他情况下没有必要,因为我们切换-prune
到总是返回 false。
提示:您可以使用find -D opt expr 2>&1 1>/dev/null
它来查看它是如何优化和扩展的,
find -D search expr 2>&1 1>/dev/null
以查看检查了哪个路径。
你可以试试下面:
find ./ ! \( -path ./tmp -prune \) ! \( -path ./scripts -prune \) -type f -name '*_peaks.bed'
对我来说,这个解决方案不适用于带有 find 的命令 exec,真的不知道为什么,所以我的解决方案是
find . -type f -path "./a/*" -prune -o -path "./b/*" -prune -o -exec gzip -f -v {} \;
解释:与 sampson-chen 相同,但添加了
-prune - 忽略...的处理路径
-o - 如果不匹配则打印结果,(修剪目录并打印剩余结果)
18:12 $ mkdir a b c d e
18:13 $ touch a/1 b/2 c/3 d/4 e/5 e/a e/b
18:13 $ find . -type f -path "./a/*" -prune -o -path "./b/*" -prune -o -exec gzip -f -v {} \;
gzip: . is a directory -- ignored
gzip: ./a is a directory -- ignored
gzip: ./b is a directory -- ignored
gzip: ./c is a directory -- ignored
./c/3: 0.0% -- replaced with ./c/3.gz
gzip: ./d is a directory -- ignored
./d/4: 0.0% -- replaced with ./d/4.gz
gzip: ./e is a directory -- ignored
./e/5: 0.0% -- replaced with ./e/5.gz
./e/a: 0.0% -- replaced with ./e/a.gz
./e/b: 0.0% -- replaced with ./e/b.gz
尝试类似的东西
find . \( -type f -name \*_peaks.bed -print \) -or \( -type d -and \( -name tmp -or -name scripts \) -and -prune \)
如果我弄错了,请不要太惊讶。如果目标是执行(而不是打印),只需将其替换到位。
通过这些解释,您可以实现您的目标和许多其他目标。只需按照您的意愿加入每个部分。
模型
find ./\
-iname "some_arg" -type f\ # File(s) that you want to find at any hierarchical level.
! -iname "some_arg" -type f\ # File(s) NOT to be found on any hirearchic level (exclude).
! -path "./file_name"\ # File(s) NOT to be found at this hirearchic level (exclude).
! -path "./folder_name/*"\ # Folder(s) NOT to be found on this Hirearchic level (exclude).
-exec grep -IiFl 'text_content' -- {} \; # Text search in the content of the found file(s) being case insensitive ("-i") and excluding binaries ("-I").
例子
find ./\
-iname "*" -type f\
! -iname "*pyc" -type f\
! -path "./.gitignore"\
! -path "./build/*"\
! -path "./__pycache__/*"\
! -path "./.vscode/*"\
! -path "./.git/*"\
-exec grep -IiFl 'title="Brazil - Country of the Future",' -- {} \;
谢谢!
[参考文献: https://unix.stackexchange.com/q/73938/61742]
额外的:
您可以将上面的命令与您喜欢的编辑器一起使用并分析找到的文件的内容,例如...
vim -p $(find ./\
-iname "*" -type f\
! -iname "*pyc" -type f\
! -path "./.gitignore"\
! -path "./build/*"\
! -path "./__pycache__/*"\
! -path "./.vscode/*"\
! -path "./.git/*"\
-exec grep -IiFl 'title="Brazil - Country of the Future",' -- {} \;)