“PATH”变量中是否可以添加通配符?

“PATH”变量中是否可以添加通配符?

设想:

父文件夹包含许多子文件夹(例如数百个),其中包含可执行文件或源程序。比如说,父文件夹/opt/app1/bin/包含许多子文件夹,mod1, mod2, ..., modn。将它们全部添加到PATH变量中可能会超出每行字符数限制,或者可能非常笨拙!

从用户dogbane的回答可以理解什么是通配符来选择目录中的所有目录那:

  1. 通配符*/可用于匹配目录,并且
  2. 通配符**/*/可用于匹配目录和子目录。

如果我将条目添加/opt/app1/bin/**/*/PATH变量中,是否会在子文件夹中搜索搜索可执行文件?这样做会不会有什么并发症?

答案1

shell 中没有每行字符数限制。您可能会想到的是,如果命令行的长度以及当前环境变量及其值的集合太大,则无法执行外部命令。这仅在执行外部命令时(即,当 shell 必须使用 C 库的exec()函数之一来启动其他可执行文件时)成为限制。设置变量的值并不执行任何外部命令。

您无法将文件名通配模式按原样添加到PATH变量中,因为 shell 在使用该变量时不会对该变量执行文件名扩展。

您可以添加扩张PATH如果您确保各个项目由 分隔,则将文件名通配模式添加到您的变量中:。由于 的值中目录路径的分隔符PATH是冒号,因此该路径名列表中包含的名称不能包含冒号。

bashshell 中,您可以针对您的模式/opt/app1/bin/**/*/使用以下内容:

shopt -s globstar failglob

IFS=:$IFS

set -- /opt/app1/bin/**/*/
PATH=$PATH:"$*"

IFS=${IFS#?}

这会将位置参数列表设置为您的通配模式扩展到的扩展路径名列表(如果您愿意,您可以使用数组,但这会需要更多的输入)。然后将该列表扩展并添加到变量值的"$*"末尾。PATH

"$*"将 set 的第一个字符扩展IFS为冒号将确保列表的元素由冒号分隔。

IFS然后恢复原来的值。

failglob如果没有模式匹配,我将用来终止脚本。如果您希望PATH在没有与您的模式匹配的情况下保持不变,您可以使用

shopt -s globstar nullglob

IFS=:$IFS

set -- /opt/app1/bin/**/*/
PATH=$PATH${1+:"$*"}

IFS=${IFS#?}

这用于nullglob代替failglob并避免修改PATHif$1未定义,即,如果模式不匹配任何内容。

答案2

是的,添加扩张/opt/app1/bin/**/*/PATH 变量(假设您已经为 shell 设置了相应的选项以导致**扩展)将导致在这些目录中搜索可执行文件。

请注意,此处的尾随*/是无关的;您可以简单地使用 的扩展/opt/app1/bin/**/来获取 下所有子目录的列表/opt/app1/bin

我没有看到长度限制$PATH 的 POSIX 规范,在基本定义 -- 环境变量 -- 其他环境变量中给出。

我能想象的并发症是:

  • 屏蔽相同的命令——给定两个相同的可执行文件名称,找到的那个(并插入到 PATH 中)第一的将是默认调用的那个

  • 未能找到错误命令时会出现额外的延迟(因为您的 shell 会在所有这些目录中搜索该命令)

相关内容