如何同时重命名目录中的多个文件


12

我说的目录/var/tmp/abc有4个文件:

12345-ram-3e3r5-io9490-89adu9.csv
45434-dam-qwe35-to9490-43adu9.csv
11234-cam-yy3r5-ro9490-85adu9.csv
14423-sam-hh3r5-uo9490-869du9.csv

我想以最短的方式(可能是单线)重命名所有CSV文件(查找所有文件并重命名):

XXXXX-ram-3e3r5-io9490-89adu9.csv
XXXXX-dam-qwe35-to9490-43adu9.csv
XXXXX-cam-yy3r5-ro9490-85adu9.csv
XXXXX-sam-hh3r5-uo9490-869du9.csv

Answers:


15

rename -n 's/(\w+)/XXXXX/' *.csv

-n开心的时候去掉。


2
对于合适的版本rename。我想这是Larry Wall的rename,从 rename包中Debian和衍生物(IIRC和prename在RedHat的劝说系统)。一个非常有用的工具。
xenoid

2
perl-rename在arch linux中
lesmana

1
@SHawarden,我尝试执行命令并阅读手册页的相关部分以了解替换模式,但是添加verbose标志时,即使当前路径具有名称与相似的文件12345_foo.csv。我是否需要执行任何其他任务才能使其正常运行(当前在Fedora 30上)?这比循环更干净。提前致谢!
danieldeveloper001 '19

3
@ danieldeveloper001您使用rename还是prename?看到我上面的评论。man {the command}最后列出作者。
氙气

2
这仅适用于Debian衍生的系统。 Fedora派生的系统具有完全不同的rename命令。参见unix.stackexchange.com/a/238862/135943-
通配符

11

尝试:

for f in *.csv; do mv -i -- "$f" "XXXXX-${f#*-}"; done

怎么运行的:

  • for f in *.csv; do

    这将启动所有*.csv文件的循环。

  • mv -i -- "$f" "XXXXX-${f#*-}"

    这将根据需要重命名文件,在覆盖任何文件之前以交互方式询问。

  • done

    这标志着循环的结束。

例:

$ ls -1
11234-cam-yy3r5-ro9490-85adu9.csv
12345-ram-3e3r5-io9490-89adu9.csv
14423-sam-hh3r5-uo9490-869du9.csv
45434-dam-qwe35-to9490-43adu9.csv
$ for f in *.csv; do mv -i -- "$f" "XXXXX-${f#*-}"; done
$ ls -1
XXXXX-cam-yy3r5-ro9490-85adu9.csv
XXXXX-dam-qwe35-to9490-43adu9.csv
XXXXX-ram-3e3r5-io9490-89adu9.csv
XXXXX-sam-hh3r5-uo9490-869du9.csv

4

我喜欢您发布的小挑战,因此这是我的解决方案。我假设所有文件都以5个数字字符开头,因此请使用cut命令将初始数字文件替换为“ XXXXX”。

下面是命令前的文件。

-rw-rw-r--. 1 daniel daniel 0 May 13 23:18 11111_bar_file.csv
-rw-rw-r--. 1 daniel daniel 0 May 13 22:54 12345_baz_file.csv
-rw-rw-r--. 1 daniel daniel 0 May 13 22:54 67890_foo_file.xml

下面是一个班轮命令。

for src in *.csv; do dst=XXXXX$(echo $src| cut -c6-); mv $src $dst; done;

下面是命令后的文件。

-rw-rw-r--. 1 daniel daniel 0 May 13 22:54 67890_foo_file.xml
-rw-rw-r--. 1 daniel daniel 0 May 13 22:54 XXXXX_bar_file.csv
-rw-rw-r--. 1 daniel daniel 0 May 13 23:18 XXXXX_baz_file.csv

那是您要找的东西吗?:)

参考文献:

在bash中循环浏览命令输出

bash中的子字符串


2
Bash可以执行这种字符串操作,无需为每个操作派生新的过程,请其他答案提供有关方法。
chx

1
@chx,已经看到了其他答案并从中获得了一些知识,但是感谢您指出这些答案。请详细说明一下no need to fork a new process for each吗?
danieldeveloper001 '19

3
cut是一个单独的二进制文件(/usr/bin/cut),运行它比使用shell内置插件消耗更多的资源。
chx

2
我知道,意图是否要重命名许多文件实际上很重要。谢谢你的澄清!
danieldeveloper001 '19

1

没有叉子:

ls | perl -lne '$suf=substr($_,6); rename $_, "XXXXX-$suf"'

使用shell循环时,mv每个文件分叉一次。Perl的rename命令没有。

(Perl的rename命令有一些限制,但是在这种特定情况下,这些限制不适用。)

至于rename前面显示的命令,yes是可行的,但是然后您会在两种不同的重命名之间产生所有混淆,以此类推。如果您有合适的选择,那很好,但如果没有,这也可行。

如果您没有perl-rename命令并且无法安装它,则可以执行以下操作:

ls | perl -lne '$old=$_; s/(\w+)/XXXXX/; rename $old, $_'

如您所见,这使用了顶部答案中所示的相同替换。当然,perl重命名还有其他优点(-n已经提到了最重要的答案,然后是-0-f等等),并且您需要的越多,应该安装的内容就越多,而不用这种方式滚动。


管道的通常实现将具有分叉。
muru

我的意思是,“不会为每个文件重命名一次”,甚至与shell都不一样,在外壳程序中,“ mv”会分叉/ usr / bin / mv或其他东西。这是因为“重命名”命令是一个Perl内部命令,可直接在libc中调用rename()。当然有一些限制,但是在此特定示例中,这些限制不适用。
锡塔拉姆

1
rename命令也是如此(最重要的答案,也使用Perl),因此也许您应该在答案上添加一些解释,而不仅仅是“不分叉”。
大师
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.