使用 mv 重命名多个文件以更改扩展名

使用 mv 重命名多个文件以更改扩展名

我想重命名文件以更改其扩展名,有效地寻求完成

mv *.txt *.tsv

但是当这样做时我得到:

*.tsv 不是目录

我觉得有点奇怪,前 10 个谷歌点击显示mv应该像这样工作。

答案1

我知道这并不能回答您的问题,但如果您正在寻找与解决方法循环相比的另一种方法来重命名文件,为什么不使用find?我曾多次使用此命令来替换包含数十万个文件的大型目录中的文件扩展名。这应该适用于任何兼容 POSIX 的系统:

find . -name "*.gappedPeak" -exec sh -c 'mv "$1" "${1%.gappedPeak}.bed"' _ {} \;

命令分解:

  1. '.' => 从当前目录开始的搜索路径,以 ' 标记。 '

  2. -name=> 设置查找匹配名称(在本例中为所有以 结尾的文件 .gappedPeak

  3. -exec=> 在每场比赛中执行以下命令

  4. sh -c=> 'exec' 为每场比赛创建一个独立的 shell 环境

  5. mv "$1" "${1%.gappedPeak}.bed"=>mv第一个变量(表示为1 美元),即当前文件名,更改为新名称。这里我做了一个子串匹配并删除;所以再次取第一个var,1 美元并用于从字符串中%删除。.gappedPeak最后.bed的 只连接剩余的变量,在下面的示例中,该变量现在是, 与,创建新的文件名。testNumber.bedtestNumber.bed

  6. 下划线是占位符$0

  7. {}被命令找到的每个 ( *.gappedPeak) 文件名替换find,并变为1 美元sh命令。

  8. \;标志着命令的结束-exec。您也可以使用';'";"

例子:

[user@before]# ls -lh
total 0
-rw-r--r--. 1 root root 0 Jan 26 11:40 test1.gappedPeak
-rw-r--r--. 1 root root 0 Jan 26 11:40 test2.gappedPeak
-rw-r--r--. 1 root root 0 Jan 26 11:40 test3.gappedPeak
-rw-r--r--. 1 root root 0 Jan 26 11:40 test4.gappedPeak
-rw-r--r--. 1 root root 0 Jan 26 11:40 test5.gappedPeak

[user@after]# ls -lh
total 0
-rw-r--r--. 1 root root 0 Jan 26 11:40 test1.bed
-rw-r--r--. 1 root root 0 Jan 26 11:40 test2.bed
-rw-r--r--. 1 root root 0 Jan 26 11:40 test3.bed
-rw-r--r--. 1 root root 0 Jan 26 11:40 test4.bed
-rw-r--r--. 1 root root 0 Jan 26 11:40 test5.bed

答案2

这个答案不会帮助您更改扩展名,但会帮助您理解为什么您的命令没有执行您期望的操作。

当您发出命令时:

mv *.txt *.tsv

shell,让我们假设 bash,扩大通配符如果有任何匹配的文件(包括目录)。文件列表将传递给程序,此处为mv。如果未找到匹配项,则传递未扩展版本。

再次:扩展模式,而不是程序。


大量的例子也许是理解为什么这行不通的最好方法。那么我们开始吧:

示例1:

$ ls
file1.txt file2.txt

$ mv *.txt *.tsv

现在线上发生的事情mv贝壳扩展*.txt到匹配的文件。因为没有*.tsv未更改的文件。

mv命令称为有两个特殊参数:

  • argc:参数数量,包括程序。
  • argv:参数数组,包括作为第一个条目的程序。

在上面的例子中,这将是:

 argc = 4
 argv[0] = mv
 argv[1] = file1.txt
 argv[2] = file2.txt
 argv[3] = *.tsv

mv程序检查最后一个参数是否*.tsv是一个目录。否则,程序将无法继续,因为它不是为连接文件而设计的。 (将所有文件合并为一个。)它也不能随心所欲地创建目录。

结果,它中止并报告错误:

mv: target ‘*.tsv’ is not a directory

示例2:

现在如果你说:

$ mv *1.txt *.tsv

mv命令的执行方式为:

 argc = 3
 argv[0] = mv
 argv[1] = file1.txt
 argv[2] = *.tsv

现在,再次mv检查是否*.tsv存在。由于没有,该文件file1.txt被移动到*.tsv.即:该文件被重命名为*.tsv带有星号和all.

$ mv *1.txt *.tsv
‘file1.txt’ -> ‘*.tsv’

$ ls
file2.txt *.tsv

示例3:

如果你改为说:

$ mkdir *.tsv
$ mv *.txt *.tsv

mv命令的执行方式为:

 argc = 3
 argv[0] = mv
 argv[1] = file1.txt
 argv[1] = file2.txt
 argv[2] = *.tsv

由于*.tsv现在是一个目录,因此文件最终会被移动到那里。


现在:使用命令,例如some_command *.tsv当意图实际保留通配符时,应该始终引用它。通过引用可以防止通配符在存在任何匹配项时被扩展。例如说mkdir "*.tsv"

示例4:

如果您这样做,可以进一步查看扩展,例如:

$ ls
file1.txt file2.txt

$ mkdir *.txt
mkdir: cannot create directory ‘file1.txt’: File exists
mkdir: cannot create directory ‘file2.txt’: File exists

实施例5:

现在:该mv命令可以并且确实适用于多个文件。但如果有两个以上,最后一个必须是目标目录。 (您可以选择使用该-t TARGET_DIR选项,至少对于 GNU mv 而言。)

所以这是可以的:

$ ls -F
b1.tsv  b2.tsv  f1.txt  f2.txt  f3.txt  foo/

$ mv *.txt *.tsv foo

这里mv将被调用:

 argc = 7
 argv[0] = mv
 argv[1] = b1.tsv
 argv[2] = b2.tsv
 argv[3] = f1.txt
 argv[4] = f2.txt
 argv[5] = f3.txt
 argv[6] = foo

所有文件最终都在目录中foo


至于你的链接。您提供了一个(在评论中),其中根本mv没有提及,但是rename.您是否有更多可以表达您的主张的链接或手册页可以分享?

答案3

mv *.txt *.tsv不起作用;mv一次只能重命名一个文件。您要么误解了这些解释,要么它们是错误的。

mmv并且rename可以一次重命名多个文件。但 around 有两个版本,rename其调用方式不同。这里应该有很多关于这一点的问题。

答案4

例如,如果运行命令时目录中有asd.txt和文件,它会尝试将这两个文件移动到名为 的目录中。因为没有这个目录,所以报错。qwe.txtmv *.txt *.tsv*.tsv

相关内容