我想重命名文件以更改其扩展名,以期有效地完成
mv *.txt *.tsv
但是当这样做时,我得到:
* .tsv不是目录
我觉得Google的前10个热门节目mv
应该像这样工作有点奇怪。
我想重命名文件以更改其扩展名,以期有效地完成
mv *.txt *.tsv
但是当这样做时,我得到:
* .tsv不是目录
我觉得Google的前10个热门节目mv
应该像这样工作有点奇怪。
Answers:
发出命令时:
mv *.txt *.tsv
如果有任何匹配的文件(包括目录),那么外壳程序(假设bash)将扩展通配符。文件列表将传递到该程序,在此处。如果未找到匹配项,则将传递未扩展的版本。mv
再说一次:shell扩展了模式,而不是程序。
大量示例也许是最好的方法,所以我们开始:
$ 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
现在,如果您改为说:
$ mv *1.txt *.tsv
使用以下mv
命令执行命令:
argc = 3
argv[0] = mv
argv[1] = file1.txt
argv[2] = *.tsv
现在,再次mv
检查是否*.tsv
存在。由于没有将文件file1.txt
移动到*.tsv
。也就是说:文件将*.tsv
使用星号和全部重命名为。
$ mv *1.txt *.tsv
‘file1.txt’ -> ‘*.tsv’
$ ls
file2.txt *.tsv
如果您改为说:
$ 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"
。
如果您这样做,则可以进一步查看该扩展:
$ ls
file1.txt file2.txt
$ mkdir *.txt
mkdir: cannot create directory ‘file1.txt’: File exists
mkdir: cannot create directory ‘file2.txt’: File exists
现在:该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
。如果您有更多链接,则可以共享。以及您声称要表达的手册页。
我知道这不能解决您的问题,但是如果您正在寻找另一种方法来命名文件,而不是使用替代方法循环,为什么不使用find
?我已经多次使用此命令将大型目录中的文件扩展名替换为其中的数十万个文件。这可以在任何POSIX兼容系统上工作:
find . -name "*.gappedPeak" -exec sh -c 'mv "$1" "${1%.gappedPeak}.bed"' _ {} \;
命令分解:
'
.
'=>搜索路径从当前目录开始,并以'标记。'
-name
=>设置查找匹配名称(在这种情况下,所有以结尾的文件.gappedPeak
)
-exec
=>在每次比赛中执行以下命令
sh -c
=>'exec'为每个匹配创建一个独立的shell环境
mv "$1" "${1%.gappedPeak}.bed"
=>mv
第一个变量(用$ 1表示)是当前文件名,变为新名称。在这里,我进行子字符串匹配并删除;因此,再次使用第一个var,$ 1,并使用从字符串中%
删除.gappedPeak
。该.bed
在刚刚结束串接剩余的变量,它现在只是,与,创建新的文件名。test#
.bed
test#.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
file.abc
-> blub.xyz
在多个子目录中的另一个简化示例:find . -name "file.abc" -exec sh -c 'mv "$1" "$(dirname $1)/blub.xyz"' _ {} \;
mv *.txt *.tsv
不起作用;mv
一次只能重命名一个文件。您可能误解了说明,或者它们是错误的。
mmv
并rename
可以一次重命名多个文件。但是rename
周围有两个版本,它们的名称不同。这里应该有很多问题。
rename
,而不是mv
。
mv *.txt *.tsv
mv
(通常)看不到*.txt
或*.tsv
只能看到shell扩展的文件名。这些通配符扩展为的文件数将是“随机”的。唯一可行的方法是,存在一个文件名*.txt
,该文件名应重命名为(字面意义)*.tsv
(不得引用该bash
选项,nullglob
不得设置)。
foo.txt
和一个名为baz.tsv
的mv *.txt *.tsv
将覆盖现有.tsv
文件...
例如,如果在运行命令时目录中有asd.txt
和qwe.txt
文件mv *.txt *.tsv
,它将尝试将这两个文件移动到名为的目录中*.tsv
。因为没有这样的目录,所以会给出错误。
要考虑的另一种选择是使用:
cp -p *.txt *.tsv
rm -f *.txt
*.txt
文件复制到,*.tsv
同时使用-p
标志保留其属性。*.txt
mv
仅更改/ directory / filename而不实际移动文件的速度慢,除非它们位于不同的分区上。