【问题标题】:How can I process a list of files that includes spaces in its names in Unix?如何在 Unix 中处理名称中包含空格的文件列表?
【发布时间】:2010-09-28 14:42:11
【问题描述】:

我正在尝试列出目录中的文件并在 Mac OS X 提示符中对它们执行一些操作。

应该是这样的:for f in $(ls -1);回声 $f;完成

如果我的文件名中没有空格(fileA.txt、fileB.txt),则回显可以正常工作。 如果文件的名称中包含空格(“file A.txt”、“file B.txt”),我会得到 4 个字符串(file、A.txt、file、B.txt)。

我尝试引用列表命令,但它只是改变了问题。

如果我这样做: for f in $(ls -1);回声 $f;完毕 我得到:文件 A.txt\n文件 B.txt

(它显示正确,但它是一个字符串,我需要将 2 行分开。

【问题讨论】:

    标签: macos unix list shell file


    【解决方案1】:

    尽可能远离 ls。使用 findutils 包中的 find。

    find /target/path -type f -print0 | xargs -0 your_command_here

    -print0 将导致 find 输出由 NUL 字符(ASCII 零)分隔的名称。 xargs 的 -0 参数告诉它也期望由 NUL 字符分隔的参数,所以一切都会正常工作。

    /target/path 替换为您的文件所在的路径。

    -type f 只会定位文件。将-type d 用于目录,或完全省略以获取两者。

    your_command_here 替换为您将用于处理文件名的命令。 (注意:如果你在 shell 中使用 echo for your_command_here 运行它,你将把所有东西都放在一行上——不要被那个 shell 工件弄糊涂了,xargs 无论如何都会做预期的正确事情。)

    编辑:或者(或者如果你没有 xargs),你可以使用效率低得多的

    find /target/path -type f -exec your_command_here \{\} \;

    \{\} \;{} ; 的转义符,它是当前处理文件的占位符。然后 find 将调用 your_command_here 并将 {} ; 替换为文件名,并且由于 your_command_here 将由 find 而不是由 shell 启动,因此空格无关紧要。

    第二个版本的效率会降低,因为 find 将为找到的每个文件启动一个新进程。如果 xargs 认为这样做是安全的,那么它足够聪明,可以将命令传递给新启动的进程。如果可以选择,请首选 xargs 版本。

    【讨论】:

    • 如果您需要对一个文件运行多个命令,xargs 就不能很好地工作。当然,您可以使用 shell 脚本作为单个命令。
    • 是的。然后总是有 -exec 参数要查找(尽管正如您所指出的,大多数问题都可以通过单独的 shell 脚本使用 xargs 重新表述。)
    【解决方案2】:
    for f in *; do echo "$f"; done
    

    应该做你想做的。你为什么用ls而不是*

    一般来说,在 shell 中处理空格是一个 PITA。看看$IFS 变量,或者在 Perl、Ruby、Python 等中更好。

    【讨论】:

    • 如果只需要一个简单的 ls -1,那么可以:用 * 替换它。不过,OP 可能还有其他要求 - 例如,在按时间修改顺序处理文件时,我总是遇到这个问题。
    • 好吧,每当你使用 ls 时,你或多或少都会遇到这个问题,因为文件名可以有换行符。您需要切换到其他方法(例如,find/xargs、perl/ruby/python、bash 数组 + 大量工作)
    【解决方案3】:

    这是 derobert 讨论的使用 $IFS 的答案 http://www.cyberciti.biz/tips/handling-filenames-with-spaces-in-bash.html

    【讨论】:

      【解决方案4】:

      您可以将参数通过管道传输到read。比如cat目录下的所有文件:

      ls -1 | while read FILENAME; do cat "$FILENAME"; done
      

      这意味着您仍然可以使用ls,就像您在问题中所说的那样,或者任何其他产生$IFS 分隔输出的命令。

      while 循环使对参数执行几项操作变得更加容易,并且在我看来使复杂的处理更具可读性。一个人为的例子:

      ls -1 | while read FILE
      do
          echo 1: "$FILE"
          echo 2: "$FILE"
      done
      

      【讨论】:

      • 如果只有空格(和制表符)会有帮助;如果名称中有换行符,则无济于事。 find -print0 和 xargs -0 在这种情况下确实有帮助。
      【解决方案5】:

      看看 --quoting-style 选项。 例如, --quoting-style=c 会产生:

      $ ls --quoting-style=c

      “file1”“file2”“目录一”

      【讨论】:

        【解决方案6】:

        查看 xargs 的手册页:

        它是这样工作的:

        ls -1 /tmp/*.jpeg | xargs rm

        【讨论】:

        • 这最多只是答案的一小部分——如果没有更完整的解释,你的答案是没有帮助的。
        猜你喜欢
        • 2020-01-25
        • 2011-12-22
        • 1970-01-01
        • 2013-05-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-01-13
        相关资源
        最近更新 更多