Ubuntu 16.04
#!/bin/bash
site="hello"
wDir="/home/websites/${site}/httpdocs/"
for file in $(find "${wDir}" -name "*.css")
do
echo "$file";
done
exit 0;
開始ディレクトリを定義してもshellcheckは警告を表示しますが、スクリプトは問題なく機能します。
root@me /scripts/ # shellcheck test.sh
In test.sh line 6:
for file in $(find "${wDir}" -name "*.css")
^-- SC2044: For loops over find output are fragile. Use find -exec or a while read loop.
for
出力に対してfind
ループを使用することは、せいぜいアンチパターンです。 BashFAQ/001-ファイル(データストリーム、変数)を行ごと(および/またはフィールドごと)に読み取るにはどうすればよいですか? を参照してください。 while
コマンドを使用して、以下のようにread
ループを使用します。以下のコマンドは、find
の出力をNULLバイトで区切り、read
コマンドはそのバイトを分割して読み取ります。これにより、名前に特殊文字が含まれるすべてのファイルが安全に処理されます(改行を含む)。
#!/usr/bin/env bash
site="hello"
wDir="/home/websites/${site}/httpdocs/"
find "${wDir}" -name "*.css" -type f -print0 | while IFS= read -r -d '' file; do
printf '%s\n' "$file"
done
または、パイプラインの使用を完全に避け、プロセス置換を行います
while IFS= read -r -d '' file; do
printf '%s\n' "$file"
done< <(find "${wDir}" -name "*.css" -type f -print0)
Web ShellCheck は、上記の2つのスニペットのいずれについても問題を報告しません。
問題は、シェルチェックが正確に伝えていることです。for
の出力を反復するfind
ループ、または同様のコマンドは壊れやすいものです。例えば:
$ ls
'a file with spaces'
$ for file in $(find . ); do echo "$file"; done
.
./a
file
with
spaces
安全な方法は、find
の-exec
を使用することです。
$ find . -exec echo {} \;
.
./a file with spaces
または、while
ループを使用するには:
$ find . -print0 | while IFS= read -r -d '' file; do echo "$file"; done
.
./a file with spaces