使用find命令但排除两个目录中的文件

问题描述 投票:0回答:7

我想查找以

_peaks.bed
结尾的文件,但排除
tmp
scripts
文件夹中的文件。

我的命令是这样的:

 find . -type f \( -name "*_peaks.bed" ! -name "*tmp*" ! -name "*scripts*" \)

但是没有成功。

tmp
script
文件夹中的文件仍会显示。

有人对此有想法吗?

linux shell unix find
7个回答
235
投票

以下是如何使用

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
考虑整个路径=)


24
投票

使用

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"
下每个节点的表达式。

查找表达式只是条件评估。

  • \( \)
    - 分组操作(您可以使用
    -path "./tmp" -prune -o -path "./scripts" -prune -o
    ,但它更详细)。
  • -path "./script" -prune
    - 如果
    -path
    返回 true 并且是一个目录,则为该目录返回 true 并且不下降到该目录。
  • -path "./script" ! -prune
     - 评估结果为 
    (-path "./script") AND (! -prune)
    。它将 prune 的“始终为真”恢复为始终为假。它避免将 
    "./script"
     打印为匹配项。
  • -path "./script" -prune -false
     - 由于 
    -prune
     始终返回 true,因此您可以在后面加上 
    -false
     来执行与 
    !
     相同的操作。
  • -o
     - 或运算符。如果两个表达式之间没有指定运算符,则默认为 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
 查看检查了哪条路径。


8
投票
这是您可以做到的一种方法...

find . -type f -name "*_peaks.bed" | egrep -v "^(./tmp/|./scripts/)"
    

2
投票

您可以尝试以下方法:

find ./ ! \( -path ./tmp -prune \) ! \( -path ./scripts -prune \) -type f -name '*_peaks.bed'
    

1
投票
对我来说,这个解决方案不适用于带有 find 的命令执行程序,真的不知道为什么,所以我的解决方案是

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
    

1
投票
通过这些解释,您可以实现您的目标以及

许多其他目标。只需按照您想要的方式加入每个部分即可。

型号

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",' -- {} \;)
    

1
投票
尝试类似的事情

find . \( -type f -name \*_peaks.bed -print \) -or \( -type d -and \( -name tmp -or -name scripts \) -and -prune \)

另一种方法使用-and

和否定路径:

find . -type f \( -not -path "*undesired1*" \) -and \( -not -path "*undesired2*" \) -iname "*your_search*"
如果我弄错了,请不要太惊讶。  如果目标是执行(而不是打印),只需将其替换到位即可。

© www.soinside.com 2019 - 2024. All rights reserved.