`chmod:bash xargs脚本中缺少操作数`

`chmod:bash xargs脚本中缺少操作数`,bash,Bash,我在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 apach

我在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.
有什么问题吗?
提前谢谢

当您可以在find的结果上运行一个循环时,为什么要使用|和tee来使用多个级别的间接寻址使事情复杂化呢

至于您看到的错误,tee的输出由涉及chown的xargs使用,除此之外,它不可用,因为它在最后一级xargs的标准输出中不可用。要使其可用,请进行另一级别的传递

find . -group websites -type f -print0 | tee >(xargs -0 chgrp apache) | tee >(xargs -0 chown apache) | xargs -0 chmod 400
或者更好,只需使用xargs-0一次,然后在子shell中一次性运行命令集

find . -group websites -type f -print0 | xargs -0 -I '{}' sh -c 'chgrp apache "{}"; chown apache "{}"; chmod 400 "{}"'
正如在注释中所建议的,上述方法可能存在漏洞,因为我们将文件名替换为脚本文本,而不是在命令行上作为单独的参数传递它们。该方法可以按照他的建议进行修改

find . -group websites -type f -print0 | xargs -0 sh -c 'for f; do chgrp apache "$f"; chown apache "$f"; chmod 400 "$f"; done' _

当您可以在find的结果上运行一个循环,如下所示时,为什么要使用|和tee来使用多个级别的间接寻址使事情复杂化呢

至于您看到的错误,tee的输出由涉及chown的xargs使用,除此之外,它不可用,因为它在最后一级xargs的标准输出中不可用。要使其可用,请进行另一级别的传递

find . -group websites -type f -print0 | tee >(xargs -0 chgrp apache) | tee >(xargs -0 chown apache) | xargs -0 chmod 400
或者更好,只需使用xargs-0一次,然后在子shell中一次性运行命令集

find . -group websites -type f -print0 | xargs -0 -I '{}' sh -c 'chgrp apache "{}"; chown apache "{}"; chmod 400 "{}"'
正如在注释中所建议的,上述方法可能存在漏洞,因为我们将文件名替换为脚本文本,而不是在命令行上作为单独的参数传递它们。该方法可以按照他的建议进行修改

find . -group websites -type f -print0 | xargs -0 sh -c 'for f; do chgrp apache "$f"; chown apache "$f"; chmod 400 "$f"; done' _
让我来做这项工作 更简单的解决方案可能如下所示:

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-0chown没有向stdout写入输出,所以xargs-0chmod从未收到任何输入

当您想从tee写入两个以上的进程时,如果您更关心的是一致性而不是一点点的速度,请对最后一个甚至所有进程使用进程替换,然后将stdout重定向到/dev/null

因此:

……或者

tee >(xargs -0 chgrp apache) >(xargs -0 chown apache) >(xargs -0 chmod 400) >/dev/null
但是当您可以chown apache:apache同时设置所有权和组时,将chgrp和chown作为单独的命令运行是愚蠢的;此外,最好在将一组未知的文件名附加为参数之前,将其作为选项结束符使用,这样做可以确保以破折号开头的参数将被视为文件名,而不是选项。

让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-0chown没有向stdout写入输出,所以xargs-0chmod从未收到任何输入

当您想从tee写入两个以上的进程时,如果您更关心的是一致性而不是一点点的速度,请对最后一个甚至所有进程使用进程替换,然后将stdout重定向到/dev/null

因此:

……或者

tee >(xargs -0 chgrp apache) >(xargs -0 chown apache) >(xargs -0 chmod 400) >/dev/null

但是当您可以chown apache:apache同时设置所有权和组时,将chgrp和chown作为单独的命令运行是愚蠢的;此外,最好在将一组未知的文件名附加为参数之前,将其作为选项结束符使用,这样做可以确保以破折号开头的参数将被视为文件名,而不是选项。

xargs-0 chown apache使用tee的输出,而不会将任何内容留给xargs-0 chmod 400。试试找-组网站-键入f-print0 | tee>xargs-0 chown apache:apache | xargs-0 chmod 400。@CharlesDuffy,他没有添加答案。xargs-0 chown apache消耗tee的输出,而xargs-0 chmod 400没有留下任何内容。试试找-集团网站-类型f-print0 | tee>xarg
s-0 chown apache:apache | xargs-0 chmod 400@CharlesDuffy,他没有添加答案。