我的 unix 目录中有一堆文件,如下所示:
filename_1234567.txt
我需要通过将每个文件名的最后三个字符复制到文件名的前面来重命名它们,如下所示:
567_filename_1234567.txt
注意:扩展名和文件名都是可变的。
我在 Solaris 机器上运行它。
答案1
和zsh
:
autoload zmv
zmv -n '*(???).*' '$1_$f'
高兴的时候就删掉-n
。
答案2
那么您希望将文件基名的最后三个字符(后跟下划线)添加到文件名的前面吗?
#!/bin/bash
EXT=.txt
for file in *${EXT}; do # presuming all the filenames have no spaces
base=${file%${EXT}}
prefix=${base:(-3)}
newname=${prefix}_${base}${EXT}
mv ${file} ${newname}
done
这在 Korn shell 中不起作用,因为它使用的技巧是bash
特定的:
ksh[3]: prefix=${base:(-3)}: bad substitution
答案3
我喜欢做这样的事情:
#!/bin/sh
for i in filename_*.txt; do echo "$i"; done |
sed "s/filename_\([0-9]*\)\([0-9]\{3\}\)\.txt/mv -i 'filename_\1\2.txt' '\2_filename_\1\2.txt'/g"
mv
这将打印完成任务的命令列表。如果它打印出正确的命令,则只需| sh
在 sed 命令末尾附加即可使 shell 执行它们。
该脚本使用sed
subsitute 命令s
和反向引用功能来使用替换字符串中匹配的正则表达式的部分内容。
s/regex/replacement/
\(
正则表达式模式中和之间的部分\)
可以在替换字符串中引用,\N
其中 in 是数字。
答案4
纯awk
解决方案:基本思想是提取基本名称的最后 3 个字符,这意味着子字符串形式length - 6
(6 因为需要考虑.txt
扩展名)到length - 3
.在这里,我只是先将该子字符串提取到 VAR 中,然后创建包含mv
要运行的两个文件名的命令;最后我要求system
函数运行命令。
代码:
awk 'BEGIN{
VAR=sprintf("%s",substr(ARGV[1],length(ARGV[1])-6,3));
CMD=("mv "ARGV[1]" "VAR"_"ARGV[1]);
print CMD;
system(CMD);
close(CMD)
}' filename_1234567.txt
演示:
$ awk 'BEGIN{VAR=sprintf("%s",substr(ARGV[1],length(ARGV[1])-6,3)); CMD=("mv "ARGV[1]" "VAR"_"ARGV[1]); print CMD; system(CMD); close(CMD)}' filename_1234567.txt
mv filename_1234567.txt 567_filename_1234567.txt
$ ls filename_1234567.txt
ls: cannot access filename_1234567.txt: No such file or directory
$ ls 567_filename_1234567.txt
567_filename_1234567.txt
$