当目录名称中包含空格时使用查找结果

时间:2013-02-22 17:37:30

标签: bash shell

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

for dir in `find . -type d`; do chmod 755 "$dir"; done
然而,它抱怨不存在的目录。只需从循环中打印目录名称(将chmod 755 "$dir"替换为echo "$dir"),我就知道当目录名称中有空格时会出现问题。会发生的是for循环会在每个换行符空格中分割find的结果。

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

3 个答案:

答案 0 :(得分:7)

此问题的常见解决方案是:

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

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

所以在你的情况下...

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

你根本不需要shell循环。

答案 1 :(得分:4)

以下是您的工具包的更多选项。如果只有一个命令可以在文件/目录组上执行,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)

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

答案 2 :(得分:1)

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

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