jsonファイルセットがあります。各ファイルにはjsonオブジェクトが含まれており、すべて同じスキーマを持ちます。ファイル名をjsonのフィールドに変更したいと思います。どうすればいいですか?
私はこの解決策を思い出しました。
find . -name '*.json' | xargs -i mv {} $(cat {} | jq '.billingAccountList[0]' | tr -d \").json
cat
しかし、{}を解釈しようとしているのでうまくいきません。 xargsが説明できることを願っています。私には、次のエラーが発生します。
cat: {}: No such file or directory
答え1
ループを使用してファイルを1つずつ処理します。
たとえば、次のようになりますwhile read
。
find . -name '*.json' | while read fname; do
newname=$(jq -r '.billingAccountList[0]' "${fname}").json
mv "${fname}" "${newname}"
done
可能ですが、次のようにfor
ファイル名のスペースに敏感です。
for fname in $(find . -name '*.json'); do
... (same as above) ...
また、ファイルを次の場所に移動することに注意してください。現在の元のパスが削除されたため、ディレクトリ構造を維持するには、次の手順を実行します。
find . -name '*.json' | while read fname; do
fdir=$(dirname "${fname}")
newname=$(jq -r '.billingAccountList[0]' "${fname}").json
mv "${fname}" "${fdir}/${newname}"
done
修正するjq -r
:@steeldriverが提案したように使用されます。ありがとうございます!
答え2
jq -r
以下を使用して、生(引用符なし)文字列を出力できる必要があります。tr
また、親ディレクトリに基づいてファイル名を変更し(たとえば、値がある.billingAccountList[0]
場合は新しい名前は代わりにする必要があります)、実装に次のものがあるとします。path/to/file.json
foo
path/to/foo.json
foo.json
find
-execdir
だから私は次のことをします
find . -name '*.json' -execdir sh -c '
echo mv -- "$1" "$(jq -r ".billingAccountList[0]" < "$1").json"
' find-sh {} \;
または(少なくともGNUの場合find
)、より効率的です。
find . -name '*.json' -execdir sh -c '
for f; do echo mv "$f" "$(jq -r ".billingAccountList[0]" < "$f").json"; done
' find-sh {} +
echo
正しいことをしていると確信している場合は、削除してください。
答え3
zsh
を使用するとzmv
(より良い衝突処理のために):
autoload zmv
zmv -n '(**/)*.json(#qD.)' '$1$(jq -r '.billingAccountList[0]' < $f).json
(幸せなら削除-n
)。