>我在 centos 7 中有一个文件夹,如下所示:
[root@localhost www]# ls -all
-rw-r--r-- 1 apache websites 191 Apr 23 2018 robots.txt
drwxrwx--- 3 websites websites 38 May 14 2018 functions
我想将这些文件夹和文件权限更改为:
[root@localhost www]# ls -all
-r-------- 1 apache apache 191 Apr 23 2018 robots.txt
drx------- 3 apache apache 38 May 14 2018 functions
我尝试了如下 bash 脚本:
find . -group websites -type f -print0 | tee >(xargs -0 chgrp apache) | xargs -0 chown apache | xargs -0 chmod 400
find . -group websites -type d -print0 | tee >(xargs -0 chgrp apache) | xargs -0 chown apache | xargs -0 chmod 500
但是我得到错误:
chmod: missing operand after ‘400’
Try 'chmod --help' for more information.
chmod: missing operand after ‘500’
Try 'chmod --help' for more information.
怎么了? 提前感谢!
当您可以使用|
和tee
对find
的结果运行循环时,为什么要使用多个级别的间接寻址使事情复杂化,如下所示
while IFS= read -r -d '' file; do
chgrp apache "$file"
chown apache "$file"
chmod 400 "$file"
done < <(find . -group websites -type f -print0)
以及以下目录
while IFS= read -r -d '' dir; do
chgrp apache "$dir"
chown apache "$dir"
chmod 500 "$dir"
done < <(find . -group websites -type d -print0)
您完全可以通过引入一个条件来检查find
结果的目录,从而
while IFS= read -r -d '' content ; do
chgrp apache "$content"
chown apache "$content"
[[ -d $content ]] && chmod 500 "$content" || chmod 400 "$content"
done < <(find . -group websites -print0)
至于您看到的错误,您的tee
的输出被涉及chown
的xargs
消耗,除此之外不可用,因为它没有tee
-ed 输出(在标准输出中可用)用于最后一个xargs
级别。要使其可用,请制作另一个级别的通行证
find . -group websites -type f -print0 | tee >(xargs -0 chgrp apache) | tee >(xargs -0 chown apache) | xargs -0 chmod 400
或者更好的是,只需使用xargs -0
一次,然后在子外壳中一次性运行命令集
find . -group websites -type f -print0 | xargs -0 -I '{}' sh -c 'chgrp apache "{}"; chown apache "{}"; chmod 400 "{}"'
正如Charles Duffy在评论中建议的那样,上述方法可能容易受到攻击,因为我们将文件名替换为脚本文本,而不是将它们作为单独的参数传递到命令行上。可以按以下方式修改该方法(他的建议)
find . -group websites -type f -print0 | xargs -0 sh -c 'for f; do chgrp apache "$f"; chown apache "$f"; chmod 400 "$f"; done' _
让find
做工作
更简单的解决方案可能如下所示:
find . -group websites
-exec chown apache:apache -- {} +
-exec chmod u=rX,g=,o= -- {} +
因为我们使用的是u=rX
,它只为已经可执行的目录或文件设置+x
,所以我们只能使用一个根本不过滤类型的find
命令来执行此操作。
整个模式之所以有效-exec ... {} +
是因为向调用的每个命令添加尽可能多的参数,就像xargs
一样;使用它,您根本不需要xargs
,因此您也不需要tee
拆分为多个xargs
命令
使tee
解决方案发挥作用
原始解决方案的问题在于您正在从xargs -0 chown apache
管道到xargs -0 chmod
。因为chown
,因此xargs -0 chown
,没有将输出写入标准输出,所以xargs -0 chmod
从未收到任何输入。
当您想从tee
写入两个以上的进程时,对除最后一个进程之外的所有进程(甚至所有进程,然后将 stdout 重定向到/dev/null
,如果您更关心一致性而不是一点点速度)。
因此:
tee >(xargs -0 chgrp apache) >(xargs -0 chown apache) | xargs -0 chmod 400
。或。。。
tee >(xargs -0 chgrp apache) >(xargs -0 chown apache) >(xargs -0 chmod 400) >/dev/null
(但是当您可以chown apache:apache
同时设置所有权和组时,将chgrp
和chown
作为单独的命令运行是愚蠢的;此外,最好在附加一组未知的文件名作为参数之前使用--
作为选项结束符号 - 这样做可确保以破折号开头的参数将被视为文件名, 不是作为选项)。