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

San*_*euw 37 rename mv

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

mv *.txt *.tsv
Run Code Online (Sandbox Code Playgroud)

但是这样做时我得到:

*.tsv 不是目录

我觉得前 10 个 google hits 节目mv应该像这样工作有点奇怪。

dev*_*ull 39

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

find . -name "*.gappedPeak" -exec sh -c 'mv "$1" "${1%.gappedPeak}.bed"' _ {} \;
Run Code Online (Sandbox Code Playgroud)

命令分解:

  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的命令,并变为$ 1sh命令。

  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
Run Code Online (Sandbox Code Playgroud)

  • 很好,谢谢!有了 [bash 指南](http://tldp.org/LDP/abs/html/string-manipulation.html) 和你的解释,我就能得到一切。 (2认同)

Run*_*ium 29

当您发出命令时:

mv *.txt *.tsv
Run Code Online (Sandbox Code Playgroud)

假设 bash,如果有任何匹配的文件(包括目录),shell会扩展通配符。文件列表被传递给程序,这里。如果未找到匹配项,则传递未扩展版本。mv

再说一次:shell扩展了模式,而不是程序。


大量示例可能是最好的方法,所以我们开始吧:

示例 1:

$ ls
file1.txt file2.txt

$ mv *.txt *.tsv
Run Code Online (Sandbox Code Playgroud)

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

mv命令使用两个特殊参数调用

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

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

 argc = 4
 argv[0] = mv
 argv[1] = file1.txt
 argv[2] = file2.txt
 argv[3] = *.tsv
Run Code Online (Sandbox Code Playgroud)

mv看的程序检查,如果最后一个参数*.tsv,是一个目录。事实并非如此,该程序无法继续,因为它不是为连接文件而设计的。(通常将所有文件合并为一个。)也不要一时兴起创建目录。

结果它中止并报告错误:

mv: target ‘*.tsv’ is not a directory
Run Code Online (Sandbox Code Playgroud)

示例 2:

现在如果你说:

$ mv *1.txt *.tsv
Run Code Online (Sandbox Code Playgroud)

mv命令是通过以下方式执行的:

 argc = 3
 argv[0] = mv
 argv[1] = file1.txt
 argv[2] = *.tsv
Run Code Online (Sandbox Code Playgroud)

现在,再次mv检查是否*.tsv存在。因为它不是该文件file1.txt被移动到*.tsv. 也就是说:文件被重命名为*.tsv带有星号和全部。

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

$ ls
file2.txt *.tsv
Run Code Online (Sandbox Code Playgroud)

示例 3:

如果你说:

$ mkdir *.tsv
$ mv *.txt *.tsv
Run Code Online (Sandbox Code Playgroud)

mv命令是通过以下方式执行的:

 argc = 3
 argv[0] = mv
 argv[1] = file1.txt
 argv[1] = file2.txt
 argv[2] = *.tsv
Run Code Online (Sandbox Code Playgroud)

由于*.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
Run Code Online (Sandbox Code Playgroud)

示例 5:

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

所以这是可以的:

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

$ mv *.txt *.tsv foo
Run Code Online (Sandbox Code Playgroud)

这里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
Run Code Online (Sandbox Code Playgroud)

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


至于你的链接。您提供了一个(在评论中),其中mv根本没有提到,但是rename. 如果你有更多的链接,你可以分享。以及您声称表达了这一点的手册页。

  • 给出了 5 个没有回答问题的例子。这怎么可能是公认的答案? (8认同)

Hau*_*ing 9

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

mmv并且rename可以一次重命名多个文件。但是有两个版本的renamearound ,它们的称呼不同。这里应该有很多关于这个的问题。

  • @SanderVanderZeeuw 我不知道你在那里读到了什么。这些示例使用了 `rename`,而不是 `mv`。 (3认同)
  • @SanderVanderZeeuw 尴尬。这些人提供课程?不幸的是,我在那里看不到联系的可能性。您可以轻松检查这是否有效。但是在 `mv *.txt *.tsv` 中,`mv`(通常)不会看到 `*.txt` 或 `*.tsv`,而是看到 shell 扩展的文件名。这些通配符扩展到的文件数量将是“随机的”。唯一可行的情况是,如果有一个名为 `*.txt` 的文件应该重命名为(字面意思)`*.tsv`(不引用 `bash` 选项`nullglob` 不能设置)。 (3认同)

Eva*_*oll 6

rename(1)

rename是 Perl 的创建者 Larry Wall 的 Perl 脚本。它采用 Perl 正则表达式并对文件名进行操作。

rename 's/\.txt$/.tsv/' *.txt
Run Code Online (Sandbox Code Playgroud)

安装

Debian/Ubuntu

如果您需要rename在 Debian/Ubuntu 上安装,您可以这样做

sudo apt install rename
Run Code Online (Sandbox Code Playgroud)