如何从命令行顺序重命名多个文件?

如何重命名文件如下

AS1100801000002.RAW7AGS AS1100801001008.RAW7AH4 AS1100801002001.RAW7AH9 AS1100801003002.RAW7AHE AS1100801004009.RAW7AHT AS1100801005002.RAW7AHY AS1100801010002.RAW7AJ3 

新名字

 AS1.txt AS2.txt AS3.txt AS4.txt AS5.txt AS6.txt AS7.txt 

Ubuntu附带的rename工具在这种方面非常热门。 你可以嵌入像这样的小Perl表达式:

 rename -n 's/.+/our $i; sprintf("AS%d.txt", 1+$i++)/e' * 

这只会告诉你它会做什么。 删除-n使其成为实弹练习。

这基本上可以通过粗略定义变量并将每个文件递增来增加它。 如果你将有超过10个文件,我建议在sprintf使用一些零填充。 以下是好到999

 rename -n 's/.+/our $i; sprintf("AS%03d.txt", 1+$i++)/e' * 

……但这很容易扩展。

我不知道单个命令或实用程序会执行此操作,但是使用简单的循环很容易:

 N=1 for X in AS*RAW*; do mv $X AS$N.txt N=$(($N+1)) done 

为了改进@ Oli的答案 , Aristotle Pagaltzis的rename工具版本1.600实际上有一个内置的计数器, $N

所以你需要的只是,

 rename 's/AS.*/AS$N/' * 

安装,

  1. 下载脚本
  2. 将其保存到系统路径上的目录中(通常为/usr/local/bin/brew/usr/bin

rename允许您直接分配给$_ ,这是此问题的理想选择。

虽然我们传递给Perl rename实用程序的代码参数经常执行匹配和替换(使用s/ ),并且以这种方式解决这个问题是完全可以接受的 ,但在像你这样的情况下你真的不需要实际上正在检查或重用旧文件名的文本。 rename允许您编写任何 Perl代码,并且不需要嵌入s/ /e 。 我建议使用这样的命令:

 rename -n 'our $i; $_ = sprintf "AS%02d.txt", ++$i' * 

或者,如果您想要剪掉几个字符:

 rename -n '$_ = sprintf "AS%02d.txt", ++our$i' * 

(它可以做得更短,但不能没有牺牲清晰度。)

这两个命令都做同样的事情。 每个都显示了将进行的重命名操作。 一旦你尝试了一个,你对结果感到满意,再次运行它而不使用-n选项。 如上所述,这将生成文件名AS01.txtAS02.txt ,…, AS10.txtAS11.txt等。 您可以根据需要修改它们,然后只在您喜欢的内容时删除-n

如果要填充宽度大于2,请将2更换为更大的数字。 例如,如果由于某种原因您需要文件名(如AS00000000000001.txt ,则应将%02d替换为%014d 。 如果您根本不想填充 – 即使这会使您的文件在以后列出时以非数字顺序显示! – 那么您可以用%d替换%02d

这是如何运作的? 在运行rename命令之前, shell会将 * 扩展为文件列表。 列表按字典顺序(即按字母顺序)按照当前的区域设置进行排序。 rename接收文件名作为命令行参数,并按列出的顺序处理它们。 表达式++$i计算结果大于变量$i的当前值,并将变量$i设置为新增加的值。 此值传递给sprintfsprintf其格式化并将其放在其他文本中。 此文本直接分配给特殊变量$_ ,该变量保存文件名。 由于rename按照它们作为参数传递的顺序处理文件,因此它们会相应地编号。


您可能已经注意到与Oli的答案相似!

两者都声明并递增一个计数器变量,并且两者都使用sprintf以基本相同的方式嵌入该计数器的值,在左侧用零填充,在新文件名的另一个文本中。 (关于如何用零填充的答案中的信息 – 以及更改填充宽度 – 甚至同样适用于两者。)它们如此相似的原因是旧答案中的方法实际上只是这样做1 ,但是使用额外的步骤,这些步骤对许多问题很有用,但实际上并不是必需的。

为了比较,这里是该答案中的第二个命令看起来如果被修改为使用我在这里使用的样式(并且填充宽度为2,正如我在这里所做的那样,而不是3):

 rename -n 's/.+/our $i; sprintf "AS%02d.txt", ++$i/e' * 

该命令中s/.+//e之间s/.+/部分现在与我在此答案的第一个命令中分配给$_的表达式(即=运算符右侧的代码)相同。

  • s/ 运算符尝试匹配文本(shell从*展开的文件名,并在运行rename时作为命令行参数传递)与正则表达式匹配,并执行替换。 /被用作分隔符来分隔s表达式的不同部分。 第一部分, .+ ,是正则表达式; 它匹配任何1个字符( . ) ,并且这样做一次或多次( + ) 。 由于文件名永远不会是空的 – 它们总是至少有一个字符长 – 这是匹配任何1个文件名的一种方法。
  • 然后它从每个匹配产生文本 – 也就是说,从每个完整的文件名 – 包含our $i; sprintf "AS%02d.txt", ++$i our $i; sprintf "AS%02d.txt", ++$i 。 这会产生新的文件名。 通常,使用s/生成文本,或者(a)替换仅与文件名的一部分匹配的文本,或者(b)以某种方式基于匹配的文本(例如,它可能使用特殊变量,如$&扩展到匹配)。 但是,在这种情况下,匹配的文本根本没有被使用。
  • 通常是替换文本our $i; sprintf "AS%02d.txt", ++$i our $i; sprintf "AS%02d.txt", ++$i将用作文件名, 作为代码运行。 但是最后的/e标志导致该文本被视为Perl源代码并进行评估,并使用这样做的值(在本例中,Perl的内置sprintf函数的返回值)作为新文件名。

虽然我认为我在这里展示的方法对于这个问题比使用s/ with /e任何方法都更清晰,更简单,但是要注意这种技术是很好的,因为它非常适合于其他一些文件。重命名检查和/或保留全部或部分原始文件名的问题。 我推荐Oli (他也写过这个答案 )的博客文章 ,其中包括一些这样的例子。

1 从技术上讲, $_ =命令和s/ /e命令的行为有所不同。 在正则表达式.+ ,并不完全正确. 匹配任何字符,因为它与换行符不匹配。 你很可能不应该使用带有换行符的文件名,但你可以,偶尔也会偶然命名一个文件。 如果您愿意,请将rename -n 'our $i; $_ = sprintf "AS%02d.txt", ++$i' $'foo\nbar'的输出与rename -n 'our $i; $_ = sprintf "AS%02d.txt", ++$i' $'foo\nbar'对比rename -n 'our $i; $_ = sprintf "AS%02d.txt", ++$i' $'foo\nbar' rename -n 'our $i; $_ = sprintf "AS%02d.txt", ++$i' $'foo\nbar'rename -n 's/.+/our $i; sprintf "AS%02d.txt", ++$i/e' $'foo\nbar' rename -n 's/.+/our $i; sprintf "AS%02d.txt", ++$i/e' $'foo\nbar' 要做. 匹配换行符,使用s标志,最后一个(用e )。 也就是说,写/se结尾而不是/e

假设您要重命名的文件位于~/Adir ,这些是此文件夹中的唯一文件,则:

 n=0 for f in $( ls ~/Adir | sort ) ; do n=$(( n+1 )) mv -n "$f" "AS${n}.txt" done 

这个脚本将查看~/Adir中的每个文件,并将其重命名为AS1.txt, AS2.txt, ...如果文件不存在(不会有任何覆盖)。 这就是为什么你应该确保这些是~/Adir中的唯一文件。 sort命令是为了防止文件保持初始顺序。

虽然OP需要命令行选项,但它也可以作为Nautilus中的GUI选项使用,非常简单。

选择所有必需的文件,然后按F2。 有一个名为自动编号的选项。 您可以将其附加到您需要的文本中。