使用第一个字段替换和第二个作为搜索条件批量重命名匹配文件

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