ファイルセットの名前を各ファイルの文字列に変更します。

ファイルセットの名前を各ファイルの文字列に変更します。

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.jsonfoopath/to/foo.jsonfoo.jsonfind-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)。

関連情報