4

必须有一种方法可以在下面我粗略构建的脚本中简化这 3 条查找线...

#!/usr/bin/bash
#
#
if [ "find /data -type f -perm 400 -print" ] ; then
    find /data -type f -perm 400 -exec echo Modifying {} \;
    find /data -type f -perm 400 -print | xargs chmod 755
else
    echo 'No files to modify'
fi
4

2 回答 2

4

您可以将其更改为以下内容:

found=$(find /data -type f -perm 400 -print -quit)

if [ "$found" ]; then
    find /data -type f -perm 400 -exec echo Modifying {} \; -exec chmod 755 {} \; 
else
    echo 'No files to modify`
fi

解释:

  • find /data -type f -perm 400 -print -quit:一旦找到第一个400具有in权限/data的文件,它就会打印文件名并立即终止查找。打印被保存到变量中found(所以我们知道是否稍后输出“No files to modify”)。
  • -exec echo Modifying {} \; -exec chmod 755 {} \;:您可以通过此链接语法对 find 返回的每个结果执行多个命令
  • 注意:当什么都没找到时显然会find返回0,所以 using$?在这里不起作用。
于 2012-11-15T19:31:49.237 回答
4
while read -d $'\0' file; do
    found=yes
    echo "Modifying $file"
    chmod 755 "$file"
done < <(find /data -type f -perm 400 -print0)
if [ "x$found" != "xyes" ]; then
    echo "No files found to modify"
fi

这使用了Bash 中的进程替换功能。相当于

find ... | while read ...

除了在这种情况下,while read在子shell中执行,所以我们不能设置将在外壳中看到的变量。相反,我们可以使用进程替换。<(cmd)在子 shell 中运行cmd,其标准输出重定向到命名管道。该管道的名称被替换到外部命令中。

然后我们使用<从这个管道重定向到while read命令的标准输入,它依次读取每个分隔记录,并将值存储在指定的名称中(file在本例中)。默认情况下,read换行符换行。对于大多数文件来说,这很好;你可以这样做:

while read file; do
    ...
done < <(find /data -type f -perm 400)

它会正常工作。但是从技术上讲,文件名中可以​​有换行符,在这种情况下会中断。-print0find的参数和 的-d $'\0'参数read导致它们每个都使用空字符作为分隔符,这在文件名中无效。

于 2012-11-15T19:39:46.383 回答