如何将查找结果存储在变量中,以便在修改它们之前可以显示它们?

如何将查找结果存储在变量中,以便在修改它们之前可以显示它们?

我有这个脚本可以查找权限不正确的文件。如果发现任何问题,它会询问用户是否要修复它们或显示它们。查找结果存储在变量中以避免多次运行相同的命令:

#!/usr/bin/env sh

results=$(find "$0" -type f -not -perm 644)

if [ -z "$results" ]; then
    echo 'No files with incorrect permissions found'
else
    while true; do
        read -p 'Fix files with incorrect permissions? (yes/no/show) ' ans
        case "$ans" in
            Y | y | yes)
                echo 'Changing file permissions...'
                chmod 644 "$results"
                break;;
            N | n | no)
                break;;
            S | s | show)
                echo "$results";;
            *)
                echo 'Please answer yes or no';;
        esac
    done
fi

问题是chmod由于换行符而引发错误:

chmod: cannot access 'test/foo'$'\n''test/bar'$'\n''test/foo bar': No such file or directory

如果我删除周围的引号"$results",效果会好一点,但是当然包含空格的文件名会出现问题。

我一直在搞乱,IFS=$'\n'但不知道应该在哪里设置。这似乎不起作用:

IFS=$'\n' chmod 644 $results

然而,这确实:

IFS=$'\n'
chmod 644 $results
unset IFS

我想我只是想知道这是否正确或者是否有更好的方法。

答案1

设置IFS为仅换行符会有所帮助,但它仍然会留下以下问题:1)带有换行符的文件名(显然),以及2)带有全局字符的文件名。例如,名为的文件*将扩展到目录中的所有文件名。

在 Bash 中,使用mapfile/readarray来填充数组:

mapfile -d '' files < <(find . -type f ! -perm 0644 -print0)
printf "%d matching files found\n" "${#files[@]}"
printf "they are:\n"
printf "  %q\n" "${files[@]}"

也可以看看:

答案2

IFS如果我在之前chmod/之后设置/取消设置它,它看起来效果同样好,而不是之前设置并在之后立即取消设置find 按照注释中的建议将子 shell 包装在数组中:

IFS=$'\n'
results=($(find "$0" -type f -not -perm 644))
unset IFS

这样,chmod 644 "${results[@]}"只要没有包含换行符的文件名,数组就有正确的项目数量,并且可以按预期工作(尽管我无法想象为什么有人会故意这样做)。

相关内容