使用第一个字段替换和第二个作为搜索条件批量重命名匹配文件
batch rename matching files using 1st field to replace and 2nd as search criteria
我有很多文件可供选择,例如
foo_de.vtt, foo_en.vtt, foo_es.vtt, foo_fr.vtt, foo_pt.vtt, baa_de.vtt, baa_en.vtt, baa_es.vtt, baa_fr.vtt, baa_pt.vtt... etc.
我创建了一个制表符分隔的文件,filenames.txt
包含当前字符串和替换字符串,例如
foo 1000
baa 1016
...etc
我想重命名所有文件以获得以下内容:
1000_de.vtt, 1000_en.vtt, 1000_es.vtt, 1000_fr.vtt, 1000_pt.vtt, 1016_de.vtt, 1016_en.vtt, 1016_es.vtt, 1016_fr.vtt, 1016_pt.vtt
我知道我可以使用像重命名这样的实用程序逐个术语地手动完成,例如:
rename 's/foo/1000/g' *.vtt
我可以将其链接到一个 awk 命令中,以便它可以 运行 通过 filenames.txt
吗?
或者有没有更简单的方法可以在 awk 中做到这一点?我知道我可以用 awk 重命名,例如:
find . -type f | awk -v mvCmd='mv "%s" "%s"\n' \
'{ old=[=11=];
gsub(/foo/,"1000");
printf mvCmd,old,[=11=];
}' | sh
如何让 awk 处理 filenames.txt 并一次完成所有这些?
This question 类似,但使用 sed。我觉得用制表符分隔这在 awk 中应该很容易?
第一次post所以请温柔点!
解决方案
感谢您的帮助。最终我能够通过将您的答案调整为以下内容来解决问题:
while read new old; do
rename "s/$old/$new/g" *.vtt;
done < filenames.txt
使用sed
while read old new; do
sed "s/$old\(.*\)/mv & $new/e" <(find . -name '*.vtt' -printf '%f\n')
done < filenames.txt
这可能对你有用(GNU sed 和重命名):
sed -E 's#(.*)\t(.*)#rename -n '\''s///'\'' *#e' ../file
这将构建一个脚本,该脚本使用 file
重命名当前目录中的文件以匹配和替换部分文件名。
一旦您对结果感到满意,请删除 -n
并执行重命名。
我假设 TSV 文件中的字符串是文字(不是正则表达式或 glob)并且要替换的部分可以位于文件名中的任何位置。
话虽如此,您可以将 mv
与 shell glob 和 bash 参数扩展一起使用:
#!/bin/bash
while IFS=$'\t' read -r old new
do
for f in *"$old"*.vtt
do
mv "$f" "${f/"$old"/$new}"
done
done < file.tsv
或使用 GNU rename
(性能更高):
while IFS=$'\t' read -r old new
do
rename "$old" "$new" *"$old"*.vtt
done < file.tsv
我有很多文件可供选择,例如
foo_de.vtt, foo_en.vtt, foo_es.vtt, foo_fr.vtt, foo_pt.vtt, baa_de.vtt, baa_en.vtt, baa_es.vtt, baa_fr.vtt, baa_pt.vtt... etc.
我创建了一个制表符分隔的文件,filenames.txt
包含当前字符串和替换字符串,例如
foo 1000
baa 1016
...etc
我想重命名所有文件以获得以下内容:
1000_de.vtt, 1000_en.vtt, 1000_es.vtt, 1000_fr.vtt, 1000_pt.vtt, 1016_de.vtt, 1016_en.vtt, 1016_es.vtt, 1016_fr.vtt, 1016_pt.vtt
我知道我可以使用像重命名这样的实用程序逐个术语地手动完成,例如:
rename 's/foo/1000/g' *.vtt
我可以将其链接到一个 awk 命令中,以便它可以 运行 通过 filenames.txt
吗?
或者有没有更简单的方法可以在 awk 中做到这一点?我知道我可以用 awk 重命名,例如:
find . -type f | awk -v mvCmd='mv "%s" "%s"\n' \
'{ old=[=11=];
gsub(/foo/,"1000");
printf mvCmd,old,[=11=];
}' | sh
如何让 awk 处理 filenames.txt 并一次完成所有这些? This question 类似,但使用 sed。我觉得用制表符分隔这在 awk 中应该很容易?
第一次post所以请温柔点!
解决方案
感谢您的帮助。最终我能够通过将您的答案调整为以下内容来解决问题:
while read new old; do
rename "s/$old/$new/g" *.vtt;
done < filenames.txt
使用sed
while read old new; do
sed "s/$old\(.*\)/mv & $new/e" <(find . -name '*.vtt' -printf '%f\n')
done < filenames.txt
这可能对你有用(GNU sed 和重命名):
sed -E 's#(.*)\t(.*)#rename -n '\''s///'\'' *#e' ../file
这将构建一个脚本,该脚本使用 file
重命名当前目录中的文件以匹配和替换部分文件名。
一旦您对结果感到满意,请删除 -n
并执行重命名。
我假设 TSV 文件中的字符串是文字(不是正则表达式或 glob)并且要替换的部分可以位于文件名中的任何位置。
话虽如此,您可以将 mv
与 shell glob 和 bash 参数扩展一起使用:
#!/bin/bash
while IFS=$'\t' read -r old new
do
for f in *"$old"*.vtt
do
mv "$f" "${f/"$old"/$new}"
done
done < file.tsv
或使用 GNU rename
(性能更高):
while IFS=$'\t' read -r old new
do
rename "$old" "$new" *"$old"*.vtt
done < file.tsv