如果我有以下 2 个文件和 1 个文件夹:
someuser@computer:~/Desktop/test$ ls -l
total 340
-rw-r--r-- 1 someuser someuser 45082 ago 5 09:56 file1.pdf
-rw-r--r-- 1 someuser someuser 291836 ago 5 09:56 file2.pdf
drwxrwxr-x 2 someuser someuser 4096 ago 5 09:56 this_is_a_folder.pdf
我运行以下命令(请注意,我省略了目的地):
cp *.pdf
file1.pdf
并file2.pdf
复制到this_is_a_folder.pdf
文件夹中。
someuser@computer00:~/Desktop/test$ ls this_is_a_folder.pdf/
file1.pdf file2.pdf
显然*.pdf
是扩展到匹配项,所以它相当于
cp file1.pdf file2.pdf this_is_a_folder.pdf
...作为this_is_a_folder.pdf
一个文件夹,然后将两个文件复制到其中。
这是一个错误吗?
这显然是通配符扩展的副作用,并且不是我期望发生的情况。
我本来期望missing destination file
错误。
答案1
这不是cp
命令中的错误。当您输入 时cp *.pdf
,cp
永远不会看到实际的通配符,因为通配符由 展开bash
,而不是由cp
。如何cp
知道您只输入了一个参数?这是 bash 通配符的副作用,不能称为错误。
答案2
你似乎非常了解正在发生的事情。在您的示例中,*pdf
确实扩展到file1.pdf file2.pdf this_is_a_folder.pdf
.我不明白你有什么困惑。cp
正在做它应该做的事情,你告诉它复制file1.pdf
并file2.pdf
进入this_is_a_folder.pdf
,这正是它正在做的事情。没有错误,它按照宣传的那样工作。
由于文件夹的名称以 结尾.pdf
,因此它包含在 中,*.pdf
并且由于它是一个文件夹,并且最后一个参数(按字母顺序排序),cp
因此将文件复制到其中。为了获得您期望的行为,您需要保护 shell 中的通配符,以便它在cp
看到它之前不会被扩展:
$ cp "*pdf"
cp: missing destination file operand after `*pdf'
Try `cp --help' for more information.
请注意,在这种情况下,通配符不会扩展,因此cp
实际上是在查找名为*.pdf
.因此,即使您使用目录作为最后一个参数 ( cp "*.pdf" foo/
) 来调用它,它也会抱怨cannot stat '*.pdf': No such file or directory
。如果您cp *pdf
在仅包含以下内容的目录中尝试,您还会看到预期的行为一.pdf
以because结尾的文件*.pdf
将被扩展为只有一个参数:
$ ls -l
total 0
-rw-r--r-- 1 terdon terdon 0 Aug 5 16:56 file1.pdf
$ cp *pdf
cp: missing destination file operand after `file1.pdf'
Try `cp --help' for more information.
还可以与此比较:
$ ls -l
total 0
drwxr-xr-x 1 terdon terdon 0 Aug 5 16:56 a_folder.pdf
-rw-r--r-- 1 terdon terdon 0 Aug 5 16:56 file1.pdf
-rw-r--r-- 1 terdon terdon 0 Aug 5 16:56 file2.pdf
$ cp *pdf
cp: target `file2.pdf' is not a directory
此处,由于文件夹名称以 开头a
,*.pdf
因此扩展为:
a_folder.pdf file1.pdf file2.pdf
。因此,cp
实际运行的命令是
cp a_folder.pdf file1.pdf file2.pdf
它返回一个错误,因为最后一个参数不是目录。
答案3
正如其他答案已经指出的那样, bash 扩展通配符,然后将其看到的内容传递给cp
.在你的情况下,cp
看到file1.pdf file2.pdf this_is_a_folder.pdf
.现在我们来阻止它。
- 不要使用通配符。
- 使用
-t
,--target-directory
开关并指定目标。 使用通配符后始终在最后声明目的地。
cp *.pdf /I/want/to/copy/files/here
答案4
如果最后一部分参数是目录,cp
则将指定的文件复制到其中。它并不关心你是否命名了你的目录foo.pdf
(为什么是这样的名字?!)。通配符扩展基于文件名(或目录名),而不是文件类型。
通过两个参数,目标可以是文件或目录。对于文件,目标文件将被删除并替换为源文件的副本。如果目标是目录,则源文件的副本将放置在该目录中。请注意给定的概要之一:
cp [OPTION]... [-T] SOURCE DEST
如果有三个或更多参数,目标将被视为目录:
cp [OPTION]... SOURCE... DIRECTORY