如何重命名目录中的文件,同时保持部分名称不变?


2

我有多个文件(大约1000个)这样命名:

abcdefg123456.xyz
abcdefg123457.xyz
abcdefg123458.xyz
abcdefg123459.xyz

一些文件在名称后面有4个附加的随机数字和字母(按任意顺序)。这些可能是重复的,但并非总是如此,因此我需要将它们更改为原始格式以验证它们是否重复。他们有这种格式:

abcdefg123456a789.xyz
abcdefg123457b987.xyz
abcdefg123458c879.xyz
abcdefg123459d897.xyz

有时,也有错误的扩展,

abcdefg123456.xyzedf
abcdefg123456.xyzfed

我想将这些文件重命名为abcdefg的原始格式,后跟原始的6个数字 - 即删除尾随的4个随机数和字母,并删除尾随的扩展名.xyz到目前为止,我所拥有的是:

rename -n "s/[a-z][0-9]{6}.xyz/.xyz/g"  *

但它似乎没有用。由于某种原因,输出是:

abcdef.xyz (no numbers)

编辑:我在选择哪个答案之间有点不知所措,因为两者都有助于找到解决方案。因为他帮助解决了问题的第二部分,所以我选择了stuts。但是你的帮助也非常感谢Mark Perryman - 当然还有评论者。


您的主要错误是使用{6}数字:对于您的示例,这应该是{3}。要在.xyz需要添加.*到匹配字符串末尾之后删除多余字符,请rename -n "s/[a-z][0-9]{3}\.xyz.*/.xyz/g" *作为命令给出(省略-n对操作感到满意的时间)。
2017年

我知道了。我正在捕捉我想要保留的部分,而不是我要删除的部分。如果无法重命名文件,我该如何删除?如果数字和字母的顺序是什么不完全...a789.xyz...b987.xyz但遵循随机模式代替:...a7b8.xyz...c9d7.xyz。谢谢。
user681866

如果第一个附加字符是一个字母,那么rename -n "s/[a-z][a-z0-9]{3}\.xyz.*/.xyz/g" *就可以了。如果没有,你不能简单地[a-z0-9]{4}在匹配模式中使用,因为这将删除标准格式文件中的最后四位数,并且您将需要使用匹配组,如在答案中,尽管您可以尝试rename -n "s/[a-z0-9]{4}\.xyz.*/.xyz/g" ?????????????????.xyz*(17个查询),应该只处理较长的文件名。请注意正则表达式匹配和shell文件扩展之间的区别。
AFH

我更新的答案(使用单引号允许$工作)和-f选项以确保删除重复文件是一个更整洁的单行解决方案;-)
Mark Perryman

Answers:


2

要删除所有文件的句号之前的4个数字/字母,可以使用以下循环:

for file in *.xyz ; do
    NEWFILE=$(echo "$file" |sed -re 's/[a-z|0-9][a-z|0-9][a-z|0-9][a-z|0-9](\.)/\./g')
    mv -v $file $NEWFILE
done

说明

for file in *.xyz ; do

循环遍历.xyz扩展名的每个文件

NEWFILE=$(echo "$file" |sed -re 's/[a-z|0-9][a-z|0-9][a-z|0-9][a-z|0-9](\.)/\./g')

NEWFILE在剥离匹配的模式[a-z|0-9][a-z|0-9][a-z|0-9][a-z|0-9](4个数字或字母的混合)之后创建一个包含文件名称的变量,后跟一个句点((\.))。

mv -v $file $NEWFILE

将文件移动到新名称,-v将以下列格式打印移动过程

`abcdefg123456a789.xyz` -> `abcdefg123456.xyz`

这当前不包括扩展的修复,但是可以使用类似的解决方案,但是使用sed命令sed 's/\.xyz.*/\.xyz/g'


谢谢你的回答。第二位效果很好。第一位不是那么多,因为最后4个随机数/字母是随机的,并不总是[letter] [3xnumber]的形式。有时会有更多的字母和地方也会发生变化。但它始终是4.编辑:通过改变位置,我的意思是它可能是[3xnumber]然后[1xletter]; 或者[2xletter],[1xnumber],[1xletter] - 但总是4.
user681866

我修改了我的解决方案,以匹配文件扩展名之前的任何字母和数字模式。让我知道这对你
有用

这会删除所有最后4个数字/字母,包括那些具有abcdefg123456.xyz格式的数字/字母。
user681866

(\.)在sed命令意味着它的字母/数字字母/数字字母/图案编号的字母/数字句号。我的测试显示这是有效的。除文件扩展名之外,文件名中是否有完整停止?
坚持2017年

不,没有。但是我通过结合你的方法和Mark的方法找到了解决方案:for file in *.html ; do NEWFILE=$(echo "$file" |sed -re 's/([a-z]*[0-9]{6})[a-z0-9]{0,4}(\.html).*/\1\2/g'); mv -v $file $NEWFILE; done至少,50个文件的初始测试似乎给出了正确的结果。我想,虽然如果我错了就纠正我,但是[a-z|0-9]在停止之前捕获4个数字虽然,这就是为什么它将所有原始文件更改为abcdefg12格式化。
user681866

1

尝试

rename -n -f 's/([a-z]*[0-9]{6})[a-z0-9]{0,4}(\.xyz).*/$1$2/g'  *

这适用于rename使用debian和ubuntu发布的版本(参见手册页http://www.computerhope.com/unix/rename.htm

这将覆盖原本会有重复名称的文件。

为什么会这样

  • ([a-z]*[0-9]{6})是捕获的abcdefg123456,可以$1在替换中称为。
  • (\.xyz)是被$2替换的捕获和引用的扩展。
  • 其他所有内容[a-z0-9]{0,4}(最多4个字母/数字)和.*(扩展后的任何内容)匹配,然后在替换中被忽略。

奖金 要删除仍然不适合您的模式的所有文件(例如,如果您没有使用上面的强制选项),则使用find列出它们并将其删除。(不用-exec rm {}干运行。)

find . -regextype posix-egrep -regex '.*/[a-z]*[0-9]{6}[a-z0-9]{4}\.xyz.*|[a-z]*[0-9]{6}\.xyz.*' -exec rm {}

1
严格来说,.xyz搜索表达式应该是\.xyz,但.当然会匹配文字.和任何其他字符。提问者的原始表达式将在您引用时起作用,但仅限于没有额外字符的文件名; 带有额外字符的名称不受影响。
2017年

谢谢你的回答。出于某种原因,我在尝试时遇到错误。\ 1最好在(eval 1)第1行写成1美元。除此之外,当它因为已存在而无法重命名文件名时,它会保留它。我知道我在OP中没有要求这个,但是如何删除该文件呢?
user681866

试试s/([a-z]*[0-9]{6})[a-z0-9]{0,4}(\.xyz).*/$1$2/g
Mark Perryman

对于删除,请检查man rename是否有force选项或类似选项。否则,运行单独的命令以删除仍与格式不匹配的文件。有点像find . -regextype posix-egrep -regex '[a-z]*[0-9]{6}[a-z0-9]{4}\.xyz.*|[a-z]*[0-9]{6}\.xyz.*' -exec rm {}但没有第-exec rm {}一次跑!
Mark Perryman

谢谢Mark,但那没用。第一个(用1美元2替换\ 1 \ 2)给了我一个错误:No such file or directory对于所有文件(使用\ 1 \ 2它会完成工作,同时给出错误)。第二个建议没有做任何事情。我并没有尝试使用-exec rm {}
user681866 2017年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.