将一组文件重命名为每个文件中存在的字符串

将一组文件重命名为每个文件中存在的字符串

我有一组 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

使用循环来逐个处理文件。

例如,与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

With zsh's zmv(为了更好地处理冲突):

autoload zmv
zmv -n '(**/)*.json(#qD.)' '$1$(jq -r '.billingAccountList[0]' < $f).json

(高兴时删除-n)。

相关内容