jqを使ってかなりの数のファイルを修正しようとしています。もしファイルには特定の値を持つ属性が含まれています。
find . \
-name '*.configuration.json' \
-type f -exec bash -c 'jq "select(.version == \"2.0\") | .identifier = \"\"" $0 | sponge "$0"' {} \;
だから私はここで実際に出力をリダイレクトする方法-exec
といいえリダイレクトされた出力を使用しますjq
。
上記のスクリプトは見つかったいくつかのファイルに対して機能しますが、他の場合はファイル全体を上書きし、何もしません。競合状態が原因で発生したようですが、この問題を解決する方法がわかりません。
私が直面できる他の落とし穴に対する助けやアドバイスをいただきありがとうございます。
答え1
式の問題は、JSONオブジェクトのキーではないjq
場合、オブジェクトが選択されず、オブジェクトが出力されないことです。これは実際にasがないすべてのアイテムを削除することを意味します。verison
2.0
2.0
version
代わりにidentifier
各オブジェクトの値が更新version
されます2.0
。
jq 'select(.version == "2.0").identifier = ""'
キーは、オブジェクトから値を抽出せずに値を更新することです。
コードにあるものと同様の次のものを使用することもできます。
jq 'select(.version == "2.0") |= (.identifier = "")'
これは更新演算子を使用して|=
選択したオブジェクトを更新しますselect()
。
そしてfind
:
find . -name '*.configuration.json' -type f -exec sh -c '
tmpfile=$(mktemp)
for pathname do
cp -- "$pathname" "$tmpfile" &&
jq "select(.version == \"2.0\").identifier = \"\"" <"$tmpfile" >"$pathname"
done
rm -f "$tmpfile"' sh {} +
また、インラインスクリプトを不必要に複数回呼び出すのを防ぎ、sh -c
スクリプト内のループを介して元のファイルの権限と所有権を保持します。
または使用したい場合sponge
(私は自分で試したことがないのでテストされていない例だと思います):
find . -name '*.configuration.json' -type f -exec sh -c '
for pathname do
jq "select(.version == \"2.0\").identifier = \"\"" "$pathname" |
sponge "$pathname"
done' sh {} +