cp 带有包含通配符的单个参数

cp 带有包含通配符的单个参数

如果我有以下 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.pdffile2.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 *.pdfcp永远不会看到实际的通配符,因为通配符由 展开bash,而不是由cp。如何cp知道您只输入了一个参数?这是 bash 通配符的副作用,不能称为错误。

答案2

你似乎非常了解正在发生的事情。在您的示例中,*pdf确实扩展到file1.pdf file2.pdf this_is_a_folder.pdf.我不明白你有什么困惑。cp正在做它应该做的事情,你告诉它复制file1.pdffile2.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

相关内容