【问题标题】:Exclude list of files from find从查找中排除文件列表
【发布时间】:2014-04-28 18:57:37
【问题描述】:

如果我在运行find 时想要排除文本文件中的文件名列表,我该怎么做?例如,我想做这样的事情:

find /dir -name "*.gz" -exclude_from skip_files

并获取 /dir 中的所有 .gz 文件,skip_files 中列出的文件除外。但是 find 没有 -exclude_from 标志。如何跳过skip_files中的所有文件?

【问题讨论】:

    标签: linux shell find


    【解决方案1】:

    我觉得你可以试试

    find /dir \( -name "*.gz" ! -name skip_file1 ! -name skip_file2 ...so on \)
    

    【讨论】:

    • 确实发现可以使用否定“!” for -name 选项
    【解决方案2】:

    我认为find 没有这样的选项,您可以使用printf 和您的排除列表构建命令:

    find /dir -name "*.gz" $(printf "! -name %s " $(cat skip_files))
    

    和做的一样:

    find /dir -name "*.gz" ! -name first_skip ! -name second_skip .... etc
    

    或者,您可以通过管道从findgrep

    find /dir -name "*.gz" | grep -vFf skip_files
    

    【讨论】:

    • 这也适用于内含物吗?我刚刚测试过,但一无所获:included_paths=("./.aws/*" "./.bash_env.m4") && find . -type f -name '*.m4' \( -path "${included_paths[0]}" $(printf " -or -path '%s'" "${included_paths[@]:1}") \)。当我直接将路径放入 find 命令时,它确实有效。
    • 首选-vw 匹配整行
    【解决方案3】:
    find /var/www/test/ -type f \( -iname "*.*" ! -iname  "*.php" ! -iname "*.jpg" ! -iname "*.png"  \)
    

    上面的命令给出了所有文件的列表,不包括扩展名为 .php、.jpg 和 .png 的文件。这个命令在腻子中对我有用。

    【讨论】:

    • PuTTY 是一个远程终端(通常使用 SSH)——它是否工作在很大程度上取决于您使用 SSH 连接的内容。
    【解决方案4】:

    这是我通常会从结果中删除一些文件的方法(在这种情况下,我查找了所有文本文件,但对我们到处都有的一堆 valgrind memcheck 报告不感兴趣):

    find . -type f -name '*.txt' ! -name '*mem*.txt'
    

    它似乎正在工作。

    【讨论】:

    • 非常适合我!
    • ! expr 如果 expr 为假则为真。
    【解决方案5】:

    Josh Jolly 的 grep 解决方案有效,但复杂度为 O(N**2),对于长列表来说太慢了。如果列表先排序(O(N*log(N)) 复杂度),您可以使用comm,它具有 O(N) 复杂度:

    find /dir -name '*.gz' |sort >everything_sorted
    sort skip_files >skip_files_sorted
    comm -23 everything_sorted skip_files_sorted | xargs . . . etc
    

    man您电脑的comm了解详情。

    【讨论】:

      【解决方案6】:

      此解决方案将遍历所有文件(不完全从 find 命令中排除),但会产生一个输出,从排除列表中跳过文件。 我发现这在运行耗时的命令时很有用 (file /dir -exec md5sum {} \;)。

      1. 您可以创建一个 shell 脚本来处理跳过逻辑并对找到的文件运行命令(使用 chmod 使其可执行,将 echo 替换为其他命令):
          $ cat skip_file.sh
          #!/bin/bash
          found=$(grep "^$1$" files_to_skip.txt)
          if [ -z "$found" ]; then
              # run your command
              echo $1
          fi
      
      1. 使用要跳过的文件列表创建一个名为 files_to_skip.txt 的文件(在您正在运行的目录上)。

      2. 然后使用 find 使用它:

          find /dir -name "*.gz" -exec ./skip_file.sh {} \;
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-11-07
        相关资源
        最近更新 更多