使用路径名扩展将文件名分配给变量

und*_*res 7 bash dash shell-script

是否有一种可靠的方法可以利用路径名扩展将文件名分配给变量?

这有效,但看起来有点狡猾:

the_file="$(echo ~/downloads/stack-*-linux-x86_64-static.tar.gz)"
Run Code Online (Sandbox Code Playgroud)

如果文件存在,则将其完整路径分配给$the_file,否则会出现虚假的 glob 模式。

Sté*_*las 7

Globbing 仅发生在列表上下文中,因此您需要分配给数组变量。随着ksh93bashzshmkshyash

the_files=(~/downloads/stack-*-linux-x86_64-static.tar.gz)
Run Code Online (Sandbox Code Playgroud)

或在sh

set -- ~/downloads/stack-*-linux-x86_64-static.tar.gz
Run Code Online (Sandbox Code Playgroud)

分配到$1$2...

并获得第一个元素:"${the_files[1]}"in zshor yash(或只是$the_files[1]in zsh)或"${the_files[0]}"in kshor bash

对于所有元素:("${the_files[@]}"也在$the_fileszsh)。

用于连接与$IFS: "${the_files[*]}"(也"$the_files"zsh)的第一个字符连接的元素。或与任何字符串中加入zsh${(j:, :)the_files}(这里加入,)。

还有一些注意事项

分配给标量变量

the_file=~/downloads/stack-*-linux-x86_64-static.tar.gz
Run Code Online (Sandbox Code Playgroud)

~会扩大,但没有水珠。但是,如果您在扩展变量时忘记使用引号,例如:

printf '%s\n' $the_file # instead of printf '%s\n' "$the_file"
Run Code Online (Sandbox Code Playgroud)

然后内容$the_file将受到 split+glob 的影响并在那时扩展这可能会让您认为它有效,而实际上它不起作用,并且在这里与波浪号扩展相结合,它甚至会变得更加混乱。

例如,如果您的$HOMEis/All * Users/me$IFS设置为其默认值,$the_file则将包含/All * Users/me/downloads/stack-*-linux-x86_64-static.tar.gzprintf打印/All当前目录中的所有文件名( 的扩展*),然后是Users/me/downloads/stack-*-linux-x86_64-static.tar.gz.

如果模式与任何文件都不匹配怎么办

在 中zsh,你会得到一个错误,但在其他 shell 中,模式保持不变。最好的方法是让模式完全扩展到无。

使用zsh,这是使用Nglob 限定符:

the_files=(~/downloads/stack-*-linux-x86_64-static.tar.gz(N))
Run Code Online (Sandbox Code Playgroud)

ksh93它的~(N)glob 运算符具有类似的功能:

the_files=(~/downloads/~(N)stack-*-linux-x86_64-static.tar.gz)
Run Code Online (Sandbox Code Playgroud)

对于其他外壳,您需要打开一些全局选项(shopt -s nullglobin bashset -o nullglobin yash)。