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