Tul*_*ova 19 shell cp wildcards arguments
如果我有以下 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
Run Code Online (Sandbox Code Playgroud)
然后我运行以下命令(注意我省略了目的地):
cp *.pdf
Run Code Online (Sandbox Code Playgroud)
file1.pdf并file2.pdf复制到this_is_a_folder.pdf文件夹中。
someuser@computer00:~/Desktop/test$ ls this_is_a_folder.pdf/
file1.pdf file2.pdf
Run Code Online (Sandbox Code Playgroud)
显然*.pdf是扩展到匹配项,所以它等价于
cp file1.pdf file2.pdf this_is_a_folder.pdf
Run Code Online (Sandbox Code Playgroud)
...和this_is_a_folder.pdf文件夹一样,然后将两个文件复制到其中。
这是一个错误吗?
这显然是通配符扩展的副作用,这不是我所期望的。
我会预料到一个missing destination file 错误。
Kar*_*tik 54
这不是cp命令中的错误。当您输入时cp *.pdf,cp永远不会看到实际的通配符,因为通配符是由 展开的bash,而不是由展开的cp。如何cp知道您只输入了一个参数?这是 bash 通配符的副作用,不能称为错误。
ter*_*don 23
你似乎非常了解正在发生的事情。在您的示例中,*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.
Run Code Online (Sandbox Code Playgroud)
请注意,在这种情况下,通配符没有扩展,因此cp实际上是在寻找名为*.pdf. 因此,即使您将目录作为最后一个参数 ( cp "*.pdf" foo/)调用它,它也会抱怨cannot stat '*.pdf': No such file or directory. 如果您尝试cp *pdf在仅包含一个以 in 结尾的文件的目录中尝试,您还将看到预期的行为,.pdf因为*.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.
Run Code Online (Sandbox Code Playgroud)
也与此比较:
$ 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
Run Code Online (Sandbox Code Playgroud)
在这里,由于文件夹的名称以 开头a,*.pdf因此扩展为:
a_folder.pdf file1.pdf file2.pdf。因此,cp实际运行的命令是
cp a_folder.pdf file1.pdf file2.pdf
Run Code Online (Sandbox Code Playgroud)
由于最后一个参数不是目录,因此返回错误。
正如其他答案已经指出的那样,bash 扩展了通配符,然后将它看到的内容传递给cp. 在你的情况下,cp看到file1.pdf file2.pdf this_is_a_folder.pdf. 现在让我们阻止它。
-t,--target-directory开关并指定目标。使用通配符后,始终在最后声明目的地。
cp *.pdf /I/want/to/copy/files/here
Run Code Online (Sandbox Code Playgroud)这不是错误,而是在 shell 中进行一次通配符扩展而不是在每个程序中实现它的副作用。
现在,您可以通过一些更奇怪的方式来解决这个问题,尤其是通过创建名称以“-”开头的文件。例如(在一个空目录中):
$ touch -- --version
$ ls
--version
$ rm *
rm (coreutils) 5.2.1
Written by Paul Rubin, David MacKenzie, Richard Stallman, and Jim Meyering.
Copyright (C) 2004 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
$ ls
--version
Run Code Online (Sandbox Code Playgroud)
通配符“*”扩展为被解释为开关的文件名。
您还可以通过在文件名中放置空格、制表符和换行符来造成混乱。