我想重命名文件以更改其扩展名,有效地寻求完成
mv *.txt *.tsv
但是当这样做时我得到:
*.tsv 不是目录
我觉得有点奇怪,前 10 个谷歌点击显示mv
应该像这样工作。
答案1
我知道这并不能回答您的问题,但如果您正在寻找与解决方法循环相比的另一种方法来重命名文件,为什么不使用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
的 只连接剩余的变量,在下面的示例中,该变量现在是, 与,创建新的文件名。testNumber
.bed
testNumber.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
答案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.txt
mv *.txt *.tsv
*.tsv