検索結果を変更する前に表示できるように変数にどのように保存しますか?

検索結果を変更する前に表示できるように変数にどのように保存しますか?

権限のないファイルを検索するスクリプトがあります。問題が検出されたら、ユーザーに問題を修正するかどうかを尋ねます。同じコマンドを複数回実行しないように、検索結果は変数に保存されます。

#!/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

IFSchmod以前に設定して直後に解除するよりも前/後に設定/解除するとうまく動作するようです。find そしてコメントで提案されているように、サブシェルを配列にラップします。

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

これにより、chmod 644 "${results[@]}"改行文字を含むファイル名がない限り、配列内の項目の数は正確で期待どおりに機能します(誰かが意図的にこれを行う理由は想像できませんが)。

関連情報