不指定目的地的`mv ./*`有什么作用?

不指定目的地的`mv ./*`有什么作用?

我不小心忘记在按回车键之前指定目的地。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 操作数指定的文件移动到由目标文件。当最终操作数未命名现有目录并且不是引用现有目录的符号链接时,采用第一种概要形式。在这种情况下,如果源文件命名一个非目录文件并且目标文件以尾随字符结尾/slashmv应将其视为错误并且不源文件将处理操作数。

在第二种概要形式中,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

相关内容