【问题标题】:Bash scripting: Find all filetypes and pathsBash 脚本:查找所有文件类型和路径
【发布时间】:2010-11-11 01:01:21
【问题描述】:

使用Bash,如何遍历指定文件夹内的文件夹,查找指定文件类型的所有文件,并且每次找到文件时,获取带文件名的完整文件路径和不带文件名的完整文件路径作为变量并传递将它们转移到另一个 Bash 脚本,执行它,然后继续搜索下一个文件?

【问题讨论】:

  • 在 Unix 中,没有“文件类型”。如果您愿意,您可以在名称中添加助记词,例如“.txt”、“.xml”、“.unicode”;但这只是名称的一部分,只是为了用户的利益。

标签: linux bash search directory


【解决方案1】:

看起来很像家庭作业。

find /path -type f -name "*.ext" -printf "%p:%h\n" | while IFS=: read a b
do
   # execute your bash script here
done

阅读 find 的手册页以获取更多 printf 选项....

【讨论】:

  • 这似乎不太对...如果%p:%h 没有空格,read a b 将把它全部放在a 中,而在b 中什么也没有,除非你设置IFS=: .
  • 决定使用 back : 因为可能有带空格的文件
  • 也很容易出现带有冒号的文件。我会使用'%p\n%h\n'read a && read b,但如果文件名带有嵌入的换行符,那仍然会失败。
  • 在 UNIX 中,任何不包含 NUL ("\0") 或 '/' 的字节序列(可能有长度限制)对于文件名都是可接受的,即使它们不是可打印字符。
  • 小心转义字符。将 find -print0 与 xargs -0 一起使用。看我更准确的答案...
【解决方案2】:

假设GNU find(这不是不合理的),您可以使用 find 来做到这一点:

find /path -type f -name '*.ext' -exec my_cool_script \{\} \;

【讨论】:

  • 那里的 \{\} 的目的是什么?比 {} 或“{}”有什么优势?
  • 这对外壳来说有点额外的安全性。 find 的手册页指出:“这两种结构都可能需要转义(使用 `\')或引用以保护它们不被 shell 扩展。”
  • 问题在于使用 exec 的 find 不能正确处理长文件列表。我有类似“行太长”之类的东西。看我的详细回答...
  • @neuro:真的吗? -exec ; 一次执行一个,如果命令行太长,你会被 findxargs 搞砸。现在,GNU findutils 过去曾出现过 -exec + 错误,但现在应该解决它们,find -exec +find -print0 | xargs -0 之间的差异非常小。
  • @ephemient :好吧,我过去曾遇到过此类错误,因此从那时起我就使用了 xargs。我当时可能遇到了一些错误。我曾经使用 -exec 但我发现使用 xargs 比 -exec 和转义序列更具可读性。 -print0 | xargs -0 是一种处理名称中空格的神奇方法,尤其是当您在 windows/mingw/cygwin 环境中使用脚本时...
【解决方案3】:

找到就是方法。使用 xargs 处理一长串文件/目录。此外,为了正确处理带有空格和类似问题的名称,我发现的最佳查找行命令是:

find ${directory} -name "${pattern}" -print0 | xargs -0 ${my_command}

诀窍是 find -print0 与 xargs -0 兼容:它将结束线替换为 '\0' 以正确处理空格和转义字符。当您的文件列表太长时,使用 xargs 可以避免一些“行太长”的消息。

您可以将 xargs 与 --no-run-if-empty 一起使用来处理空列表,并使用 --replace 来管理复杂的命令。

【讨论】:

    【解决方案4】:

    如果您安装了 GNU Parallel http://www.gnu.org/software/parallel/,您可以这样做:

    find . -name '*.ext' | parallel echo {} '`dirname {}`'
    

    用你最喜欢的 bash 命令替换 echo,用你正在寻找的文件扩展名替换 ext。

    观看 GNU Parallel 的介绍视频以了解更多信息: http://www.youtube.com/watch?v=OpaiGYxkSuQ

    【讨论】:

      【解决方案5】:

      正如一些人已经提到的,Linux/UNIX 没有强制性的文件扩展名。但是,在基于 UNIX 的系统上,许多常见文件的类型可以由 file 命令确定。以下示例使用 file 命令将名称和类型或每个文件传递给 my_script:

          find /path -type f | xargs file | while read -r line ; do my_script $line; done
      

      xargs 命令已用于最小化文件命令的 exec 数量。

      类型信息将非常广泛,从 xargs 文件步骤的以下示例输出中可以看出:

         /usr/bin/easy_install-3.8:                   Python script, ASCII text executable
         /usr/bin/splain:                             Perl script text executable
         /usr/bin/nvzoom:                             ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=e2295b7d737246db5a2986c790452139793bdbfc, for GNU/Linux 3.2.0, stripped
      
      

      关于从文件名中提取路径的其他要求可以在 my_script 中完成,或者如果必须在 my_script 之前完成,则可以使用 bash 字符串提取或 sed/awk/perl 重新格式化输出。

      如果您希望任何文件名中包含空格或其他特殊字符,那么按照之前答案中的建议,您可以使用 -print0:

          find /path -type f -print0 | xargs -0 file | while read -r line ; do my_script "$line"; done
      

      【讨论】:

        猜你喜欢
        • 2015-06-08
        • 1970-01-01
        • 2011-10-11
        • 2020-06-02
        • 2021-03-15
        • 2021-05-31
        • 1970-01-01
        • 2020-10-13
        • 2022-01-18
        相关资源
        最近更新 更多