我不小心忘记了在按回车键之前指定目的地。如果不mv ./*
指定目标位置,当前目录下的文件和目录将移至何处?
mv
接受1个论点”,事实并非如此。扩展*
。之后,它将接受shell传递给它的所有参数。
我不小心忘记了在按回车键之前指定目的地。如果不mv ./*
指定目标位置,当前目录下的文件和目录将移至何处?
mv
接受1个论点”,事实并非如此。扩展*
。之后,它将接受shell传递给它的所有参数。
Answers:
如果最后一个参数是目录,则只需将当前工作目录中的所有文件和目录(名称以点开头的文件和目录除外)都移到该目录中。如果有两个文件,则第一个文件可能已覆盖第二个文件。
这是一些示范:
超过两个文件,最后一个参数是一个文件
$ 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
。球形通常按字母顺序扩展。mv
总是看到文件和目录的列表。它永远不会看到这个球体本身。
该命令mv
支持两种类型的移动。一个是mv file ... directory
。另一个是mv old-file-name new-file-name
(或mv old-file-name directory/new-file-name
)。
首先,我将做一个测试基础-5个文件和一个文件夹:
touch file1 file2 file3 file4 file5
mkdir folder
接下来,我将运行一个测试命令。该-v
选项指定我希望将shell执行的每个命令都打印到stderr
。该-x
选项指定我希望将相同的内容打印到stderr
- 但我希望在评估命令之后但在外壳程序运行之前完成打印。
sh -cxv 'echo mv *'
echo mv *
+ echo mv file1 file2 file3 file4 file5 folder
mv file1 file2 file3 file4 file5 folder
因此,您看到我输入外壳程序echo mv *
的命令是,并且在扩展外壳程序后 执行的命令之后*
是echo mv
所有这些文件和文件夹。
默认情况下,shell会扩展glob,例如:
sh -cxv 'echo file[1-5]'
echo file[1-5]
+ echo file1 file2 file3 file4 file5
file1 file2 file3 file4 file5
这是set [+-]f
glob函数的结果:
sh -cxvf 'echo file[1-5]'
echo file[1-5]
+ echo 'file[1-5]'
file[1-5]
因此,当您在配置有默认选项mv *
的shell中运行命令时,例如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/
基本上,shell mv
将使用目录的内容(如果.
目录不为空并且不包括名称以开头的文件/文件夹)作为其参数列表执行。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操作数命名的文件移动到target_file指定的目标。当最终操作数未命名现有目录并且不是引用现有目录的符号链接时,将采用此第一摘要格式。在这种情况下,如果source_file命名为非目录文件,而target_file以结尾/slash
字符结尾,mv
则应将此视为错误,并且不会处理任何source_file操作数。在第二个摘要表中,
mv
应将由source_file操作数命名的每个文件移动到由target_dir操作数命名的现有目录中的目标文件,如果target_dir是引用现有目录的符号链接,则应引用该文件。每个source_file的目标路径应为目标目录的串联;/slash
如果目标未以a结尾,则为单个字符/slash
;以及source_file的最后一个路径名部分。当最终操作数命名现有目录时,采用第二种形式。
因此,如果*
扩展为:
两个文件
renamed
第二个文件是,第一个文件到第二个文件unlinked
。一个或多个文件,后跟一个目录或一个链接
还要别的吗
sh
东西,我忘了用它进行调试,但是关于我的原始问题,这意味着问题出在shell上mv
吗?真是令人讨厌,它比我最初想象的要简单,但这是一个真正的陷阱。
*
不是一个参数吗?对?:)
首先,shell扩展./*
到当前目录中的所有文件(以点开头的文件除外)。
mv
失败mv
失败。echo ./*
,看看您的外壳使用哪个顺序(通常是字母顺序)。
mv
如果仅使用一个参数调用,则返回错误消息。
missing destination file operand after *filename*
即使昨天没有,我历史上的命令也一样。
怎么
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
mv file1 file2 ... filen directory
几乎没有任何关系*
。
*
到file dir
其中。d
f
a b c d
是不是file ... dir
。我只有在所有的评论,因为你没有提到的那种任何地方只说*
成为file ... dir
这不会发生。