Bashスクリプト:文字列に一重引用符を追加しないでください。

Bashスクリプト:文字列に一重引用符を追加しないでください。

ある関数の出力を別の関数に渡そうとします。

set -x
OUTPUT=$(git diff --name-only --diff-filter=AM develop... | sed 's/.*/"&"/')
./bin/phpcs $OUTPUT

私の主な問題は、最初の関数がファイルのリストを返し、ファイルにスペースを含めることができることです。だから二重引用符で囲みましたが、別の関数に渡すと一重引用符が追加されます。

出力:

++ git diff --name-only --diff-filter=AM develop...
++ sed 's/.*/"&"/'
+ OUTPUT='"test file.php"
"testfile.php"'
+ ./bin/phpcs '"test' 'file.php"' '"testfile.php"'

呼び出しの主な最終目標は次のとおりです。

./bin/phpcs "test file.php" "testfile.php"

ベストアンサー1

問題は、出力されるテキストに二重引用符を追加することですgit diff。これによりパス名が壊れ、ファイルのリストを正しく解析するのが難しくなります。特に、パス名に引用符が含まれている場合はさらにそうです。

トレース出力に表示される単一引用符は、文字列がどのように区切られてbashいるかをより簡単に表示できるように追加されました(たとえば、、、、および3つの"test個別file.php""testfile.php"パラメータであることを示すため)。シェルのトレース出力は、シェルが実行するアクションに関するヒントを提供するためのデバッグ出力であり、通常はそうではありません。実際シェルによって実行されるコードです。


エクスポートしたパス名を安全に使用するには、git diff --name-onlyこの-zオプションを使用することをお勧めします。これにより、gitパス名が空の区切りリストとして出力されます。その後、それを使用してxargs -0このリストの要素に対してコマンドを実行できます。

git diff --name-only -z --diff-filter=AM develop... |
xargs -0 ./bin/phpcs

ファイルのリストを配列として読み取ることもできます。たとえば、bashシェルでは次のようになります。

readarray -d '' -t names < <( git diff --name-only -z --diff-filter=AM develop... )

./bin/phpcs "${names[@]}"

これは明らかにgit diff出力しないことに依存します。名前が多すぎます。

おすすめ記事