我想重命名文件以更改其扩展名,有效地寻找完成
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)
命令分解:
'
.' => 从以 ' 标记的当前目录开始的搜索路径。'
-name=> 设置查找匹配名称(在这种情况下,所有以 结尾的文件.gappedPeak)
-exec=> 在每场比赛中执行以下命令
sh -c=> 'exec' 为每个匹配项创建一个独立的 shell 环境
mv "$1" "${1%.gappedPeak}.bed"=>mv第一个变量(由$1表示),即当前文件名,到新名称。这里我做一个子串匹配和删除;所以再次取第一个 var,$1并用于从字符串中%删除.gappedPeak。该.bed在刚刚结束串接剩余的变量,这在下面的例子中,现在是,有,创建新的文件名。testNumber.bedtestNumber.bed下划线是$0的占位符
的
{}是由每个(替换*.gappedPeak由所发现的)的文件名find的命令,并变为$ 1到sh命令。
\;标志着-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)
Run*_*ium 29
当您发出命令时:
mv *.txt *.tsv
Run Code Online (Sandbox Code Playgroud)
假设 bash,如果有任何匹配的文件(包括目录),shell会扩展通配符。文件列表被传递给程序,这里。如果未找到匹配项,则传递未扩展版本。mv
再说一次:shell扩展了模式,而不是程序。
大量示例可能是最好的方法,所以我们开始吧:
$ 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,是一个目录。事实并非如此,该程序无法继续,因为它不是为连接文件而设计的。(通常将所有文件合并为一个。)也不要一时兴起创建目录。
结果它中止并报告错误:
Run Code Online (Sandbox Code Playgroud)mv: target ‘*.tsv’ is not a directory
现在如果你说:
$ 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)
如果你说:
$ 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"。
如果您执行以下操作,则可以进一步查看扩展:
$ 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)
现在:该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. 如果你有更多的链接,你可以分享。以及您声称表达了这一点的手册页。
mv *.txt *.tsv不起作用;mv一次只能重命名一个文件。你要么误解了解释,要么他们是错误的。
mmv并且rename可以一次重命名多个文件。但是有两个版本的renamearound ,它们的称呼不同。这里应该有很多关于这个的问题。
rename(1)rename是 Perl 的创建者 Larry Wall 的 Perl 脚本。它采用 Perl 正则表达式并对文件名进行操作。
rename 's/\.txt$/.tsv/' *.txt
Run Code Online (Sandbox Code Playgroud)
如果您需要rename在 Debian/Ubuntu 上安装,您可以这样做
sudo apt install rename
Run Code Online (Sandbox Code Playgroud)