我知道这个命令的每一部分。
sudo mv home/* *
sudo
:超级用户do,以root权限执行。mv
:移动文件或目录。home/*
: mv 命令的参数。它表示主目录的内容。星号*
是一个通配符,它扩展为当前目录中按字典顺序排列的文件列表。
下一个参数是命运文件夹。但是,我指定一个星号作为目标目录,如果执行该命令,该文件夹将完全消失。那么,*
在这种情况下是什么?
答案1
home/*
和*
是 shell 全局变量,它们首先由 shell 扩展(因此这里以您自己的身份运行,而不是使用超级用户权限),结果是然后作为参数传递给命令。
因此,如果home
包含.
, ..
, .hidden
. u1
,u2
当前目录包含.
, ..
, .hidden
, -i
, x
, y
,将接收的参数mv
是mv
, home/u1
, home/u2
, -i
, x
, y
。
mv
像 GNU 这样的一些实现mv
有一个错误特征,即以 开头的参数-
仍然被识别为选项,即使它们出现在非选项参数之后,因此上面的内容-i
将被视为一个-i
选项mv
(sudo
由于明显的原因,没有这个错误特征)。
y
将被视为目标目录,如果是目录类型(或目录的符号链接),mv
则文件将在其中消失。y
mv
不会看到*
orhome/*
参数(当然,除非确实有这样命名的文件)。但请注意,某些 shell(例如大多数类似 Bourne 的 shell)具有这样的缺陷:如果 glob 与任何文件都不匹配,则会按原样(未扩展)传递给命令。
因此,对于这些,如果当前目录仅包含隐藏文件,则将作为最后一个参数mv
接收。不进行特殊处理(shell 的作用是理解 glob),因此会将其视为目标目录的字面名称。现在,如果没有非隐藏文件,该目录也不会存在,因此只会报告有关目标目录不存在的错误。如果只有in ,则会重命名为当前目录。*
mv
*
*
mv home/u1 home/u2 *
u1
home
mv home/u1 *
mv
home/u1
*
这个错误特性是由 Bourne shell 于 1979 年引入的。在早期的 Unix 版本中(以及在没有改变它的 csh 中),如果没有一个 glob 匹配,该命令将被取消。然后,glob 被一个/etc/glob
助手扩展(glob 的名字由此而来)。如果至少有一个 glob 与任何文件匹配,则不匹配的 glob 将被删除。因此,在 csh/tcsh(或zsh -o cshnullglob
)中mv home/* *
,当前目录没有非隐藏文件的位置将变为mv home/u1 home/u2
将移动u1
到u2
.
现代 shell 像zsh
or fish
(or bash -o failglob
) 已经通过在任何 glob 不匹配时取消命令来修复它。
答案2
这完全取决于 shell 通配模式扩展到什么。
它执行以下三件事之一:
如果
*
命令末尾的 展开为名称列表,并且该列表中的最后一项是某个名称目录,然后该命令将home/*
扩展至的所有内容以及*
扩展至的所有内容(但不是最后一个目录名)移动到该目录中。如果扩展为任何内容,并且目标目录尚未包含目录,则匹配的文件和目录将与目标目录中的目录home/*
一起找到。home
home/*
home
如果
*
命令末尾的 展开为名称列表,并且该列表中的最后一项是某个名称不是目录,那么该命令将产生错误。如果
*
根本不展开(因为当前目录为空),则会产生错误。
如果使用mv
GNU coreutils 且最后*
一个匹配一个或多个以短划线开头的名称,则这可能会更改命令的功能,具体取决于选项mv
将名称解释为什么。
答案3
当我自己运行这个程序时,它最终创建了一个*
在我的目标文件夹中调用的文件夹,并且还删除了我从中获取的源文件。经过几次测试后,*
返回了“不是目录”的预期行为,并且*
未创建名为的新目录。
我相信这更符合所提出的问题,因为他表示他的文件消失并echo *
返回了*
。