如何匹配文件名中的字符串并根据字符串重命名文件?

How to match strings in file names and rename file according to string?

我有很多文件名中有匹配的字符串。

foostring.bar
barstring.bar
fuustring.bar
aha_foostring.abc
meh_barstring.abc
lol_fuustring.abc
...

我需要找到具有匹配字符串的 bar 和 abc 文件,并将 *.bar-files basename 重命名为 *.abc-files 的样子。也就是说,加一个字符串前缀。

我正在寻找的结果应该是这样的:

aha_foostring.bar
meh_barstring.bar
lol_fuustring.bar
aha_foostring.abc
meh_barstring.abc
lol_fuustring.abc
...  

澄清编辑:*.abc 文件中的字符串始终位于最后一个下划线 _ 之后和点 . 之前 字符串只包含字母和数字。前缀可以包含任意数量的字符和任意类型的字符,包括 _. 这意味着我还需要考虑以下示例。

dindongstring.bar
w_h.a.t_e_v_e.r_dingdongstring.abc

我一直在试验查找、前缀和基本名称,但我需要这里的帮助和建议。

谢谢

我会选择这样的东西: (我相信有更优雅的方法来做到这一点(awk/sed))

#!/bin/bash

for filename in *.abc
do
    prefix=${filename%_*}
    searchstring=${filename%.abc}
    searchstring=${searchstring#*_}
    if [[ -f "$searchstring.bar" ]]
    then
        mv "${searchstring}.bar" "${prefix}_${searchstring}.bar"
    fi
done
# show the result
ls -al

很抱歉在您的答案中添加了这个,但是因为我已经删除了我的答案并且您的答案最接近 OP 的需要。 (我不介意...我关心解决方案=)

编辑: 可能这就是 OP 想要的:

for f in *.abc; do
   prefix=${f%_*}
   bar=${f%.abc}
   bar="${bar##*_}.bar"
   [[ -f "$bar" ]] && mv "$bar" "${prefix}_${bar}"
done

我建议尝试以下 "magick":

$ join -j 2 <(ls -1 . | sed -n '/\.bar/s/^\(.*\)\(\.[^.]\+\)$/\t/p' | sort -k2) <(ls -1 . | sed -n '/\.abc/s/^\(.\+_\)\?\([a-zA-Z0-9]\+\)\(\.[^.]\+\)$/\t\t/p' | sort -k2) | awk '{print  " " }' | while read FILE PREFIX; do echo mv -v "$FILE" "$PREFIX$FILE"; done
mv -v barstring.bar meh_barstring.bar
mv -v dingdongstring.bar w_h.a.t_e_v_e.r_dingdongstring.bar
mv -v foostring.bar aha_foostring.bar
mv -v fuustring.bar lol_fuustring.bar

如果它会显示预期的命令,则在 mv 和 运行 之前删除 echo 以进行更改。

另请注意,我使用 ls -1 . 命令显示当前目录的文件,可能您需要更改目录或在包含文件的目录中使用 运行 命令。

小说明:

该代码背后的想法是为 .bar 和 .abc 文件创建文件名公共部分对:

$ ls -1 . | sed -n '/\.bar/s/^\(.*\)\(\.[^.]\+\)$/\t/p' | sort -k2
barstring.bar   barstring
dingdongstring.bar  dingdongstring
foostring.bar   foostring
fuustring.bar   fuustring
$ ls -1 . | sed -n '/\.abc/s/^\(.\+_\)\?\([a-zA-Z0-9]\+\)\(\.[^.]\+\)$/\t\t/p' | sort -k2
meh_barstring.abc   barstring   meh_
w_h.a.t_e_v_e.r_dingdongstring.abc  dingdongstring  w_h.a.t_e_v_e.r_
aha_foostring.abc   foostring   aha_
lol_fuustring.abc   fuustring   lol_

如您所见,第二个字段是公共部分。之后我们通过公共部分将这些列表连接在一起,只留下 .abc 文件名和前缀:

$ join -j 2 <(ls -1 . | sed -n '/\.bar/s/^\(.*\)\(\.[^.]\+\)$/\t/p' | sort -k2) <(ls -1 . | sed -n '/\.abc/s/^\(.\+_\)\?\([a-zA-Z0-9]\+\)\(\.[^.]\+\)$/\t\t/p' | sort -k2) | awk '{print  " " }'

barstring.bar嗯_ dingdongstring.bar w_h.a.t_e_v_e.r_ foostring.bar啊哈_ fuustring.bar哈哈_

最后一步是通过添加适当的前缀来重命名文件。