“mv *”如何知道移动到哪里?

Rav*_*agh 2 command-line bash directory mv

我有一个这样的目录结构:

ravikumar@ravikumar-RV409-RV509-RV709:~$ tree test
test
|
??? 1
??? 2
??? 3
??? 4
??? a
??? b
??? c
Run Code Online (Sandbox Code Playgroud)

我执行 mv 命令为:

ravikumar@ravikumar-RV409-RV509-RV709:~$ cd test/
ravikumar@ravikumar-RV409-RV509-RV709:~/test$ mv *
Run Code Online (Sandbox Code Playgroud)

结果:

ravikumar@ravikumar-RV409-RV509-RV709:~/test$ tree
.        
|
??? c
    ??? 1
    ??? 2
    ??? 3
    ??? 4
    ??? a
    ??? b
Run Code Online (Sandbox Code Playgroud)

我这里的问题是 mv Judge 如何将所有目录和文件移动到最后一个目录?那就是c

Eli*_*gan 6

当您在该目录中运行它时,mv *相当于mv 1 2 3 4 a b c. 除非-t选项,mv将最后一次非选项参数作为目的地的名称,从而感动1234a,并b全部纳入c

shell扩展 *为文件名列表。发生这种情况时,您正在运行的命令实际上不会看到*,而只会看到它扩展到的内容。因此,您运行的命令无法根据您实际键入的内容判断如何处理其参数——它只能查看 shell 传递给它的内容。

当您运行mv *,可呈现,你可能已经推断,应该总是避免-壳不是mv本身扩展命令*到一个按字母顺序排列的所有文件和目录列表包含在当前目录中,不包括任何的名字开始.

(您可以自定义通过如何工作的dotglobnullglob以及nocaseglob外壳选项和GLOBIGNORE可变见的文档获取详细信息。)

如果c不是目录,您的命令将失败,什么也不移动,并显示以下错误消息:

mv: target 'c' is not a directory
Run Code Online (Sandbox Code Playgroud)

但是因为它c是一个目录,所以它只是“有效”,即使——如果你运行命令的目的不是为了看看它会做什么——你可能打算在末尾写一个单独目录的名称该命令*

为了更直观地说明为什么mv无法知道它的参数是从 展开的*,假设您已编写:

mv 1 c
Run Code Online (Sandbox Code Playgroud)

那将移动1c. 但也许您希望将两个项目移动到c

mv 1 2 c
Run Code Online (Sandbox Code Playgroud)

或五个项目:

mv 1 2 3 4 a c
Run Code Online (Sandbox Code Playgroud)

或六项:

mv 1 2 3 4 a b c
Run Code Online (Sandbox Code Playgroud)

但是 shell 确保mv *完全相同的参数以相同的顺序传递给mv命令mv 1 2 3 4 a b c

不能通过一次调用来移动多个项目通常会很不方便mv。但是,即使这是不允许的并且总是会产生错误,您仍然可以在仅包含两个条目的目录中创建类似的混乱情况。然后mv *在该目录中运行 仍会尝试将一个移动到另一个。

如果您想知道 shell 将扩展到什么内容,您可以将您感兴趣的命令替换为printf '%s\n',它会打印所有传递给它的后续参数,并以换行符分隔。例如:

printf '%s\n' *
Run Code Online (Sandbox Code Playgroud)