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

时间:2015-02-04 14:53:03

标签: linux bash rename

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

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

我需要找到带有匹配字符串的bar和abc文件,并将* .bar-files基本名称重命名为* .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

我一直在尝试使用find,prefix和basename,但我需要帮助和建议。

由于

2 个答案:

答案 0 :(得分:2)

我会这样做: (我相信有更优雅的方法(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

答案 1 :(得分:1)

我建议尝试下面的“魔法”:

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

如果它会显示预期的命令,请在echo之前移除mv,然后再次运行以进行更改。

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

小解释:

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

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

barstring.bar meh_ dingdongstring.bar w_h.a.t_e_v_e.r_ foostring.bar aha_ fuustring.bar lol _

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

相关问题