我在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.
出什么问题了? 预先感谢!
答案 0 :(得分:3)
当您只需对|
的结果进行如下循环时,为什么使用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
的输出被xargs
所涉及的chown
占用,并且除此以外不可用,因为它不是{{1 }}-ed(在标准输出中可用)到tee
的最后一级。要使其可用,请再上一级通行证
xargs
或更妙的是,只需使用find . -group websites -type f -print0 | tee >(xargs -0 chgrp apache) | tee >(xargs -0 chown apache) | xargs -0 chmod 400
一次,然后在子外壳中一次运行即可运行一组命令
xargs -0
正如Charles Duffy在评论中所建议的那样,由于我们将文件名替换为脚本文本,而不是在命令行中将它们作为单独的参数传递,因此上述方法潜在易受攻击。可以通过以下方式修改此方法(他的建议)
find . -group websites -type f -print0 | xargs -0 -I '{}' sh -c 'chgrp apache "{}"; chown apache "{}"; chmod 400 "{}"'
答案 1 :(得分:1)
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
都没有向stdout写输出,所以xargs -0 chmod
从未收到任何输入。
当您要从tee
写两个以上的进程时,请对除最后一个之外的所有(甚至所有它们)使用进程替代(然后甚至将它们全部替代),然后将stdout重定向到{{1 }},如果您更关心一致性而不是一点点速度。
因此:
/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
同时设置所有权和组时,同时运行chgrp
和chown
作为单独的命令是很愚蠢的;而且,最好使用{{1 }}作为选项结尾符号,然后附加一组未知的文件名作为参数-这样做可以确保以破折号开头的参数将被视为文件名,而不是选项。)