通过将文件名中的数字替换为文本文件中的相应字符串来重命名一堆文件

通过将文件名中的数字替换为文本文件中的相应字符串来重命名一堆文件

我有大量文件想要重命名。每个文件名包含一个数字 (xxx): FIXED_PART_xxx_UNIQUE_PART.

我还有一个文本文件,每行都有一个数字和一个字符串:

001 string001
002 string002
...
112 string112

每个文件都有一个条目,但不一定每个条目都有一个文件。我想通过解析该xxx部分并将其替换为文件中的字符串来重命名每个文件。

最好的方法是什么?

编辑:实际的文件名如下所示:

Berlin_Ost_034_some_variable_text.jpg

因此,在这种情况下,固定部分还包含下划线,但每个文件夹都是相同的。 xxx 部分仅由数字组成。

输出将是该文件的

Berlin_Ost_Sommer_some_variable_text.jpg

我说的是 200 个文件

该文本文件包含一行:034 Sommer

这就是文件中的 034 部分被 Sommer 替换的原因

该文件包含各种字符串,但仅包含字符、数字和德语变音符号。第一部分始终是数字。这是我正在使用的文件之一的一部分

033 Winter
034 Sommer
035 Herbst
036 Frühling
037 Abends.kurz.vor.Sonnenaufgang

我正在使用Linux

答案1

假设zsh字符串不包含空格或制表符:

autoload -Uz zmv
typeset -A mapping=($(<mapping.txt))
zmv -n '(*_)([0-9](#c3))(_*.jpg)' '$1${mapping[$2]-$2}$3'

如果满意,请删除-n(试运行)。

对于包含多个下划线之间的 3 位数字序列的文件名,最右边的一位将被替换。使用${mapping[$2]-$2}可确保如果在映射中找不到该数字序列,则它将保持原样。

如果所有文件具有相同的前缀,您还可以执行以下操作:

zmv -n '(Berlin_Ost_)([0-9](#c3))(_*.jpg)' '$1${mapping[$2]-$2}$3'

如果字符串可能包含空格或空白(开头或结尾除外),则可以将关联数组构建为:

typeset -A mapping
while read -r key value; do mapping[$key]=$value; done < mapping.txt

反而。

要替换文件名中所有出现的 3 位数字,您可以执行以下操作:

zmv -n '*.jpg' '${f//(#m)[0-9](#c3)/${mapping[$MATCH]-$MATCH}'

在这种情况下,我们不会在两侧查找下划线。我们可以这样做:

zmv -n '*.jpg' '${f//(#b)_([0-9](#c3))_/${mapping[$match[1]]-$match[1]}'

但是,虽然这会取代 和001,但002foo_001_bar_002_baz.jpg不会出现,foo_001_002_bar.jpg因为第二个_将包含在第一场比赛中,因此不能成为以后比赛的一部分。

答案2

您可以遍历字符串列表中的每个条目,重命名任何匹配的文件。这可以压缩成一行,但我将其保留在此处,以便我可以附加注释:

while IFS=' ' read -r key value                            # Extract the key and value
do
    for file in *_"$key"_*                                 # Loop across all matches
    do
        [ -f "$file" ] &&
            mv -- "$file" "${file/_${key}_/_${value}_}"    # Replace key with value
    done
done <keysandvalues                                        # Read the file of matches

替换表达式将仅替换第一次出现的键,并且两侧必须用下划线界定。键和值都不能包含/.

迭代替换文件的一个副作用是,如果您的文件名包含两个替换字符串(例如,Berlin_033_other_035_text.jpg),那么两个替换字符串将在匹配时被替换(此处的结果为Berlin_Winter_other_Herbst_text.jpg)。如果存在问题,将重命名的文件移动到单独的目录可以解决此问题。

答案3

_some_variable_text这是假设不包含数字的解决方案:

$ for i in *.jpg; do
    s="$(grep "${i//[^0-9]/}" file.txt)"
    echo mv -- "$i" "${i//[0-9]*/}${s//* /}_${i//*[0-9]_/}"
    # to actually perform the command remove the echo
    # do a backup first
  done
mv -- Berlin_Ost_034_some_variable_text.jpg Berlin_Ost_Sommer_some_variable_text.jpg

  • 循环遍历文件。
  • s="$(grep "${i//[^0-9]/}" file.txt)"提取密钥;
  • mv -- "$i" "${i//[0-9]*/}${s//* /}_${i//*[0-9]_/}"使用参数替换重命名文件以获得文件名的不同部分。

答案4

一条线

prefix="foo" ls | grep -oP "(?<=${prefix}_).*" | xargs -I % sh -c 'mv ${prefix}_% ${prefix}_$( echo % | cut -d"_" -f1 | grep -f - filenames.txt | cut -d" " -f2 )_$( echo % | cut -d"_" -f2- ) '

foo前缀 (FIXED_PART) 和filenames.txt文件名称在哪里...

解释:

它获取当前目录中以 开头的所有文件名prefix,但仅匹配前缀 后面的部分grep -oP "(?<=${prefix}_).*"。对于每一行 (1),它将文件prefix+重命名(1)prefix+ (search in the file for the first part of (1), and get the corresponding string)+remaining part of (1)

瞧瞧

相关内容