5

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

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

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

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

4

3 回答 3

7

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

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

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

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

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

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

于 2013-02-22T17:40:32.610 回答
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

于 2013-02-22T20:13:27.493 回答
1

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

shopt -s globstar
for dir in **/*/; do
    chmod 0755 "${dir%/}"
done
于 2013-02-22T17:39:32.610 回答