【问题标题】:Using find results when directories have spaces in their names当目录名称中有空格时使用查找结果
【发布时间】:2013-02-08 10:01:39
【问题描述】:

我正在尝试通过制作一个简单的 bash for 循环来更改所有子目录的权限:

for dir in `find . -type d`; do chmod 755 "$dir"; done

但是,它抱怨不存在的目录。通过简单地打印循环中的目录名称(将chmod 755 "$dir" 替换为echo "$dir"),我发现当目录名称中有空格时会出现问题。发生的情况是for 循环将find 的结果拆分为每个换行空格。

我想以某种方式使其根据换行符拆分结果并忽略空格。双引号应确保字符串到达​​chmod 作为一个参数。如何更改拆分?

【问题讨论】:

    标签: bash shell


    【解决方案1】:

    尝试这样做(使用 builtins,需要 bash --version >= 4):

    shopt -s globstar
    for dir in **/*/; do
        chmod 0755 "${dir%/}"
    done
    

    【讨论】:

    • 请注意,这需要bash 4 或更高版本。
    【解决方案2】:

    这个问题通常的解决方法是:

    find ... -print0 | xargs -0 ...
    

    -print0 参数导致输出文件名以 nul 结尾,而 xargs 的 -0 / -null 参数告诉它读取这种格式。

    所以在你的情况下......

    $ find . -type d -a -print0 | xargs -0 chmod 755
    

    您实际上根本不需要 shell 循环。

    【讨论】:

    • 好的,这真的很好:)。但是当参数列表太长时,我看到一些命令会出现恐慌。使用 xargs 的 -n 参数可以解决这个问题吗?
    • 另外,当命令一次只接受一个参数时会发生什么?我意识到这比主要问题更广泛,但仍然如此。
    • 参数数量的限制通常是内核的 exec 限制,xargs 通过多次运行命令来检查和自动处理。它还可以处理真正只允许 1 的命令,使用:xargs -n 1
    • 在 Mac OS 终端中工作
    【解决方案3】:

    以下是您的工具包的更多选项。如果您只有一个命令可以在文件/目录组上执行,find 可以直接执行:

    find . -type d -exec chmod 755 {} +
    

    如果命令一次只能在一个文件/目录上运行,请使用\; 而不是+ 为每个项目运行一次:

    find . -type d -exec chmod 755 {} \;
    

    如果你需要做一些复杂的事情(即几个命令),你可以制作一个安全版本的循环:

    while IFS= read -r -u3 -d $'\0' dir; do
        sudo chown gkudelis "$dir"
        chmod 755 "$dir"
        touch "$dir/.perms_reset"
    done 3< <(find /tmp -type f -print0)
    

    请注意,这使用来自进程替换 (&lt;(...)) 的重定向而不是管道,以避免在子 shell 中运行循环;这是一个仅限 bash 的功能,因此您必须以 #!/bin/bash 而不是 #!/bin/sh 开始脚本。此外,它重定向到 fd 3 而不是 stdin,因此如果循环内的任何内容试图从 stdin 读取,它不会混淆。此外,请务必在对循环变量的所有引用(本例中为"$dir")周围使用双引号来保护其中的空格。详情请见BashFAQ #020

    【讨论】:

    • 比接受的答案更有用的答案,因为它适用于更广泛的问题。
    猜你喜欢
    • 2018-12-20
    • 2020-09-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-04-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多