我有大量文件想要重命名。每个文件名包含一个数字 (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
,但002
它foo_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)
瞧瞧