【问题标题】:Properly handle lists of files with whitespace in filename正确处理文件名中带有空格的文件列表
【发布时间】:2012-04-18 12:58:55
【问题描述】:

我想遍历 Bash 中的文件列表并执行一些操作。问题:文件名可能包含空格,这对通配符或ls 造成明显问题:

touch a\ b
FILES=* # or $(ls)

for FILE in $FILES; do echo $FILE; done

产量

a
b

现在,处理此问题的常规方法是改用find … -print0。但是,这只适用于(很好)与xargs -0 一起使用,而不是与 Bash 变量/循环一起使用。

我的想法是将$IFS 设置为空字符以使其正常工作。但是,comp.unix.shell 似乎认为this is impossible in bash

无赖。嗯,理论上是可以用其他字符的,比如:(毕竟$PATH也是用这种格式的):

IFS=$':'
FILES=$(find . -print0 | xargs -0 printf "%s:")

for FILE in $FILES; do echo $FILE; done

(输出略有不同,但足够公平。)

但是,我不禁觉得这很笨拙,应该有更直接的方式来做到这一点。 我正在寻找一种更直接的方法来完成此操作,最好使用通配符或ls

【问题讨论】:

    标签: bash loops whitespace filenames


    【解决方案1】:

    处理这个问题的最好方法是将文件列表存储为一个数组,而不是一个字符串(并确保双引号所有变量替换):

    files=(*)
    for file in "${files[@]}"; do
        echo "$file"
    done
    

    如果您想从find 的输出生成一个数组(例如,如果您需要递归搜索),请参阅this previous answer

    【讨论】:

    • 你能告诉我这种方法比柯林的优势是什么吗? – 实际上,对于我的特定目的来说,有一个非常明显的优势,因为我还需要文件的 count,这使用数组更容易获得。但除此之外,还有什么优势呢?
    • 我的作品。科林似乎只是;它实际上只是存储通配符,而不是文件列表。
    • 我听不懂。 Collin 的方法对我来说效果很好。他存储通配符并不重要,不是吗?这就是 Bash 中变量的工作方式。
    • 也许我应该说“我的工作方式符合我的预期。”我想这取决于你想要做什么:如果你想存储文件列表,请使用我的;如果要存储文件模式(并稍后生成匹配文件列表),请使用 Collin's.但是如果你使用 Collin's 就好像它存储了一个文件列表,你就会遇到麻烦:像“列表”这样的东西会随着文件的添加和删除而改变,或者你 cd 左右等等。计数条目是另一个示例:模式匹配任意数量的文件,而列表包含特定数量的条目。
    • 感谢您解释差异,我不完全确定引擎盖下发生了什么,但可以看出 glob 有效:-P
    【解决方案2】:

    您在第一个示例中的内容在 Msys Bash、Cygwin 和我的 Fedora 机器上对我来说很好:

    FILES=*
    for FILE in $FILES
    do
        echo $FILE
    done
    

    【讨论】:

    • 这实际上并不是将文件列表存储在变量中,只是未扩展的通配符。 FILES=*; echo "$FILES" 打印 *,而不是文件列表。
    【解决方案3】:

    前面的很重要

    IFS=""
    

    否则将找不到后面紧跟两个空格的文件

    【讨论】:

    • 这是不正确的。两种发布的解决方案都可以在包含两个连续空格的文件中正常工作。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-12-17
    • 2012-11-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-22
    相关资源
    最近更新 更多