我编写了一个脚本来为我执行一些文件操作。我使用通配符运算符*
将函数应用于某种类型的所有文件,但有一点我不明白。我可以将unzip
所有文件放在这样的文件夹中
unzip "*".zip
但是,要随后删除所有 zip 文件,我需要这样做
rm *.zip
也就是说,它不需要引号。另一方面,如果我只给它 *(给我一个警告“文件不匹配”),解压缩将不起作用。
为什么会有所不同?对我来说,这似乎是完全相同的操作。或者我错误地使用了通配符?
外卡介绍在 Unix 中,不要真正深入探讨这一点,而且我无法在rm
或zip
文档中找到任何内容。
我正在 Mac (Yosemite) 上使用终端。
答案1
你已经很好地解释了情况。难题的最后一部分是它unzip
本身可以处理通配符:
http://www.info-zip.org/mans/unzip.html
论点
文件[.zip]
...
通配符表达式类似于常用的 Unix shell(sh、ksh、csh)中支持的通配符表达式,并且可能包含:
* 匹配0个或多个字符的序列
通过引用 * 通配符,您可以阻止 shell 扩展它,以便 shellunzip
看到通配符并根据其自己的逻辑处理扩展它。
rm
相比之下,不支持通配符在其自己的,因此尝试引用通配符将指示rm
在文件名中查找文字星号。
unzip *.zip
不起作用的原因是unzip
的语法根本不允许多个 zip 文件;如果有多个参数,则期望第二个及后续参数是存档中的文件:
解压缩 [-Z] [-cflptTuvz[abjnoqsCDKLMUVWX$/:^]] 文件[.zip] [文件...] [-x x文件...] [-d exdir]
答案2
这两个命令之间的区别在于引号*
字符。如果您在 shell 中调用命令并使用该*
字符作为参数,则 shell 本身将计算该参数。看这个例子:
$ ls
file1.zip file2.zip file3.zip file4.txt
现在有*
:
$ ls *.zip
file1.zip file2.zip file3.zip
shell 评估通配符并构建命令,如下所示:
$ ls file1.zip file2.zip file3.zip
使用带引号的通配符,它被解释为名为(字面意思)的文件*.zip
:
$ ls "*".zip
ls: cannot access *.zip: No such file or directory
unzip
无法使用多个压缩文件作为参数来调用该实用程序。但是,开发者为此选择了另一种方式。从联机帮助页:
文件[.zip]
[...] 通配符表达式与常用 Unix shell(sh、ksh、csh)中支持的通配符表达式类似 [...] (请务必引用操作系统可能解释或修改的任何字符,特别是在 Unix 和 VMS 下。)
答案3
区别在于第一种情况是 shell 本身扩展了 glob:
% cd /
% echo *
Applications Library Network System Users Volumes bin cores ...
%
而在第二种情况下,应用程序本身会使用该文字字符执行 Something™:
% cd /
% perl -E 'chdir "/tmp" or die; say for glob($ARGV[0])' "*"
com.apple.launchd.aj4FEhYqm5
...
如果不加引号,shell 首先会展开 glob,并且该命令将使用 shell glob 展开到的任何内容来运行。
答案4
由于 zip 处理多个参数的方式,需要引号:
rm
:删除参数列表中的所有文件
zip
:解压第一个参数中的文件。仅提取剩余参数中的文件。
$ ls *.zip
file1.zip file2.zip file3.zip
$ unzip *.zip
Archive: file1.zip
caution: filename not matched: file2.zip
caution: filename not matched: file3.zip
如您所见,它尝试在 file1.zip 中查找 file2.zip 和 file3.zip
为了允许您一次提取多个 zip 文件,zip 支持自行解释 glob,并产生不同的结果。