如何将使用通配符构建并包含空格的路径存储到变量中

如何将使用通配符构建并包含空格的路径存储到变量中

情况如下(我使用的是 Mac,OS X El Capitan):

# This works:

$ cd /Applications/Adobe\ Illustrator*/Cool\ Extras.localized/en_US/Templates/;

# These do not work:

$ INSTALL_DIR=/Applications/Adobe\ Illustrator*/Cool\ Extras.localized/en_US/Templates;
$ cd $INSTALL_DIR
# Moves me here: /Applications/Adobe

$ cd "$INSTALL_DIR"
-bash: cd: /Applications/Adobe Illustrator*/Cool Extras.localized/en_US/Templates: No such file or directory

$ cd "${INSTALL_DIR}"
-bash: cd: /Applications/Adobe Illustrator*/Cool Extras.localized/en_US/Templates: No such file or directory

$INSTALL_DIR我的目标是像这样使用tar

$ tar -xz $SOURCE_ZIP --strip-components 1 -C $INSTALL_DIR "*.ait";

不幸的是,-C(更改为目标目录)不喜欢$INSTALL_DIR;中的空格。如果我使用引号,我就无法*工作。

有没有一种优雅的方法来处理这种情况?

答案1

当 * 没有被引用时,shell 在运行命令之前扩展参数列表。它将扩展参数列表传递给程序。

当 * 出现在带引号的字符串中时,它在传递给程序之前不会被 shell 扩展。

尝试扩展路径,将其分配给另一个变量,然后在将其作为参数传递时引用第二个变量。

答案2

问题不在于 tar,而在于你的 shell 代码。该选项的参数-C应该是路径,而不是通配符模式。请注意,您在使用该命令时遇到了完全相同的问题cd

您在变量中存储了通配符模式INSTALL_DIR。当您编写 时-C $INSTALL_DIR,这将应用“split+glob”运算符:获取变量的值,在空格处拆分它,并将每个单词解释为通配符模式,然后进行扩展。这里变量的值为/Applications/Adobe Illustrator*/Cool Extras.localized/en_US/Templates,分为三个词/Applications/Adobe, Illustrator*/Cool, Extras.localized/en_US/Templates;中间的单词包含通配符 ( *),因此它被解释为通配符模式,但由于它不匹配任何文件,因此该模式保持原样。这使得选项的参数-C成为 string /Applications/Adobe,然后命令还有两个参数tarIllustrator*/CoolExtras.localized/en_US/Templates

如果使用双引号,则"$INSTALL_DIR"只是变量的值INSTALL_DIR。仍然*在里面,因为它在任何时候都没有扩展过。

根据经验,通配符会在需要多个单词的上下文中扩展。毕竟,一般来说,通配符模式匹配多个文件。赋值的右侧会抑制通配符扩展,因为结果预计是单个字符串。要获取列表,请分配给数组变量而不是字符串变量:

INSTALL_DIRS=(/Applications/Adobe\ Illustrator*/Cool\ Extras.localized/en_US/Templates)

如果您安装了多个版本的 Illustrator,则可能有多个数组元素。让我们看最后一个元素。

INSTALL_DIR=${INSTALL_DIRS[$((${#INSTALL_DIRS}-1))]}

NowINSTALL_DIR是现有文件的路径(假设通配符确实匹配)。您可以正常使用它(即您可以将其展开在双引号内)。

tar -xz "$SOURCE_ZIP" --strip-components 1 -C "$INSTALL_DIR" "*.ait"

相关内容