不正な権限を持つファイルを検索するスクリプトがあります。 不正な権限を持つファイルが見つかった場合、ユーザーに修正するか表示するかを尋ねます。 検索結果は、同じコマンドを複数回実行しないように、変数に保存されます。
#!/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) glob 文字を含むファイル名の問題は依然として残ります。たとえば、 というファイルは、*
ディレクトリ内のすべてのファイル名に展開されます。
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
そしてコメントで提案されているように、サブシェルを配列でラップします。
IFS=$'\n'
results=($(find "$0" -type f -not -perm 644))
unset IFS
この方法では、配列には正しい数の項目が含まれ、chmod 644 "${results[@]}"
改行文字を含むファイル名がない限り、期待どおりに動作します (ただし、誰かがわざとこのようなことを行う理由は想像できません)。