我正在尝试通过创建一个简单的bash for
循环来更改所有子目录的权限:
for dir in `find . -type d`; do chmod 755 "$dir"; done
然而,它抱怨不存在的目录。只需从循环中打印目录名称(将chmod 755 "$dir"
替换为echo "$dir"
),我就知道当目录名称中有空格时会出现问题。会发生的是for
循环会在每个换行符和空格中分割find
的结果。
我想以某种方式让它根据换行符分割结果 并忽略空格。双引号应确保字符串作为一个参数达到chmod
。如何更改拆分?
答案 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