我需要用一个特殊的后缀将目录中所有带前缀的文件重命名为相应的名称。
例如,假设我有一堆名为的文件
first_0001.txt
second_0001.txt
first_0002.txt
second_0002.txt
...
我需要做的是重命名它们,使它们的对应名称为:
0001_1.txt
0001_2.txt
0002_1.txt
0002_2.txt
...
我试过用做这个
for file in `ls`; do
mv $file ${file/first*/*_1.txt}
done
但这只是将所有文件重命名为具有相同的名称,这是不需要的。因此,变化的模式是:
- 如果文件名以";第一_;,该部分应当被移除,并且后缀"_1〃;应添加到文件扩展名之前。例如,first_0001.txt应更改为0001_1.txt
- 类似地,如果文件名以";second_";,该部分应当被移除,并且后缀"_2〃;应添加到文件扩展名之前。例如,second_0001.txt应更改为0001_2.txt
扩展@Jonathan的答案,如果您的rename
具有-E选项:
rename -n -E 'my %map = (first => 1, second => 2)'
-e 's/(D+)_(d+)(..*)/${2}_$map{$1}$3/' {first,second}*
不是一行代码,但如果您的bash
版本支持BASH_REMATCH
。
#!/usr/bin/env bash
for file in *.txt; do
[[ $file =~ ^(first|second)_(000[12])(.txt)$ ]] &&
if [[ "${BASH_REMATCH[1]}" == first ]]; then
echo mv -v "$file" "${BASH_REMATCH[2]}_1${BASH_REMATCH[3]}"
elif [[ "${BASH_REMATCH[1]}" == second ]]; then
echo mv -v "$file" "${BASH_REMATCH[2]}_2${BASH_REMATCH[3]}"
fi
done
如果您对输出满意,请删除echo
。
如果您有基于Perl的rename
程序(有时称为prename
(,那么您可以使用它来执行这两个映射。示例显示了前缀和后缀之间的数字字符串——正则表达式可以很容易地修改以处理更通用的名称。
rename 's/first_(d)+.txt/$1_1.txt/' first_*.txt
rename 's/second_(d+).txt/$1_2.txt/' second_*.txt
然而,这并不是一个单一的命令。显然,你可以在它们之间加一个分号,然后把它们都放在一行上;我不知道这算不算。把它们结合在一起充其量是很棘手的——而且不值得付出努力
我对一句俏皮话过敏,下面是我的做法:
#!/bin/sh -
for pathname in ./*.*; do
filename=${pathname##*/}
case $filename in
'first_'* ) postfix=_1 ;;
'second_'* ) postfix=_2 ;;
# ...
* ) continue ;;
esac
path=${pathname%/*}
newname=${filename#*_} # temporary
newname=${newname%.*}
extension=${pathname##*.}
# remove `echo' if it looks good
echo mv -- "$pathname"
"$path/$newname$postfix.$extension"
done
我会执行以下操作:
for f in first_*; do g=${f#*_}; mv $f ${g%.*}_1.txt; done
for f in second_*; do g=${f#*_}; mv $f ${g%.*}_2.txt; done
但如果你真的想要一个疯狂的oneliner,你可以这样做:
for pair in first,1 second,2 ; do postfix=_${pair#*,}.txt; for file in ${pair%,*}_*.txt; do rightpart=${file#*_}; echo $file ${rightpart%.*}$postfix; done; done