権限のないファイルを検索するスクリプトがあります。問題が検出されたら、ユーザーに問題を修正するかどうかを尋ねます。同じコマンドを複数回実行しないように、検索結果は変数に保存されます。
#!/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
そしてコメントで提案されているように、サブシェルを配列にラップします。
IFS=$'\n'
results=($(find "$0" -type f -not -perm 644))
unset IFS
これにより、chmod 644 "${results[@]}"
改行文字を含むファイル名がない限り、配列内の項目の数は正確で期待どおりに機能します(誰かが意図的にこれを行う理由は想像できませんが)。