我不小心忘记在按回车键之前指定目的地。mv ./*
在不指定destination的情况下,将当前目录下的文件和目录移动到哪里?
答案1
如果最后一个参数是目录,则您只需将当前工作目录中的所有文件和目录(名称以点开头的文件和目录除外)移动到该目录中。如果有两个文件,第一个文件可能会覆盖第二个文件。
以下是一些演示:
超过两个文件且最后一个参数是一个文件
$ mkdir d1 d2 d3
$ touch a b c e
$ mv *
mv: target 'e' is not a directory
超过两个文件且最后一个参数是目录
$ mkdir d1 d2 d3
$ touch a b c
$ mv -v *
'a' -> 'd3/a'
'b' -> 'd3/b'
'c' -> 'd3/c'
'd1' -> 'd3/d1'
'd2' -> 'd3/d2'
两个文件
$ touch a b
$ mv -v *
'a' -> 'b'
进一步解释
shell 将 glob( *
) 扩展为 的参数mv
。 glob 通常按字母顺序展开。mv
总是看到文件和目录的列表。它永远看不到球体本身。
该命令mv
支持两种类型的移动。一是mv file ... directory
。另一个是mv old-file-name new-file-name
(或mv old-file-name directory/new-file-name
)。
答案2
首先,我将创建一个测试库 - 5 个文件和一个文件夹:
touch file1 file2 file3 file4 file5
mkdir folder
接下来我将运行一个测试命令。该-v
选项指定我希望 shell 执行的每个命令都打印到stderr
.该-x
选项指定我希望将相同的内容打印到stderr
-但我想要完成后该命令被评估但是前shell 运行它。
sh -cxv 'echo mv *'
输出
echo mv *
+ echo mv file1 file2 file3 file4 file5 folder
mv file1 file2 file3 file4 file5 folder
所以你会看到我向 shell 提供的命令是echo mv *
shell 执行的命令后 *
展开echo mv
后是所有这些文件和文件夹。
默认情况下 shell 将展开球体喜欢:
sh -cxv 'echo file[1-5]'
输出
echo file[1-5]
+ echo file1 file2 file3 file4 file5
file1 file2 file3 file4 file5
这是 glob 函数的结果set [+-]f
:
sh -cxvf 'echo file[1-5]'
输出
echo file[1-5]
+ echo 'file[1-5]'
file[1-5]
因此,当您在配置了默认选项的 shell 中运行命令时,例如mv *
shell 会扩展为*
单词,当前目录中的所有文件的参数列表根据区域设置排序。它执行系统exec(ve)
调用mv
(本质上)附加此参数列表。因此,mv
当 shell 对参数进行全局匹配并对它们进行排序时,会获取所有参数。除了strace
查看这些效果之外,您还可以再次使用调试,例如:
sh -s -- mv * <<\SCRIPT
sed -n l /proc/$$/cmdline
echo "$@"
SCRIPT
输出
sh\000-s\000--\000mv\000file1\000file2\000file3\000file4\000file5\000folder\
\000$
mv file1 file2 file3 file4 file5 folder
并且便携:
( PS4= IFS=/; set -x mv *; : "/$*/" ) 2>&1
输出
: /mv/file1/file2/file3/file4/file5/folder/
基本上,shellmv
使用目录的内容执行(如果它不为空且不包括名称以 开头的文件/文件夹.
)作为其参数列表。mv
如果使用两个以上的参数调用它,则 POSIX 指定将其最终参数解释为目录 - 同样的方式ln
是(因为事实上,它们在底层功能上是非常相似的工具)。
不过够echo
了:
sh -cxv 'mv *' ; ls
输出
mv *
+ mv file1 file2 file3 file4 file5 folder
folder/
所有文件都被移到最后一个参数中 - 因为它是一个文件夹。如果它不是文件夹怎么办?
sh -cxv 'cd *; mv *'; ls . *
输出
cd *; mv *
+ cd folder
+ mv file1 file2 file3 file4 file5
mv: target ‘file5’ is not a directory
.:
folder/
folder:
file1 file2 file3 file4 file5
就是这样POSIX 指定 mv
在这种情况下应该表现:
mv [-if] source_file target_file
mv [-if] source_file... target_dir
在第一个概要形式中,
mv
实用程序应将 source_file 操作数指定的文件移动到由目标文件。当最终操作数未命名现有目录并且不是引用现有目录的符号链接时,采用第一种概要形式。在这种情况下,如果源文件命名一个非目录文件并且目标文件以尾随字符结尾/slash
,mv
应将其视为错误并且不源文件将处理操作数。在第二种概要形式中,
mv
应将由 source_file 操作数命名的每个文件移动到由 source_file 操作数命名的现有目录中的目标文件目标目录操作数,或引用如果目标目录是引用现有目录的符号链接。每个 source_file 的目标路径应是目标目录、单个/slash
字符(如果目标不以 a 结尾/slash
)和最后一个路径名组成部分的串联。源文件。当最终操作数命名现有目录时,采用第二种形式。
所以如果*
扩展到:
两个文件
- 您应该只有一个文件,即
renamed
第二个 is 后的第一个到第二个文件unlinked
。
- 您应该只有一个文件,即
一个或多个文件,最后跟一个目录或指向一个或多个文件的链接
- 您应该只有一个目录或指向该目录的链接,这是其所有父级以前的内容刚刚移动的位置。
还要别的吗
- 您应该会收到一条错误消息并松一口气。
答案3
首先,shell 扩展./*
到当前目录中的所有文件(以点开头的文件除外)。
- 如果没有或只有一个文件:
mv
失败 - 如果有两个文件:第一个文件被移动到第二个文件(因此会丢失)
- 如果有两个以上文件:
- 如果最后一个是目录:所有文件都移到该目录中
- 否则
mv
失败。
答案4
有什么
mv *
作用?
这是一个简短的答案:
shell 将通配符扩展*
为目录内容列表。然后 shell 将该完整列表传递给命令。该命令从未见过*
。
该命令mv file1 file2 ... filen directory
会将 file1 ... filen 移动到目录中。
例子
这里我创建了一个包含三个文件的测试目录
$ mkdir t
$ cd t
$ echo a>a; echo b>b; echo c>c
$ ls
a b c
您无法将多个文件移动到一个文件中
$ mv *
mv: target `c' is not a directory
我们添加一个子目录
$ mkdir d
你能将多个文件移动到子目录中
$ mv *
$ ls
d
$ ls d
a b c