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

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

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

这可行,但看起来有点狡猾:

the_file="$(echo ~/downloads/stack-*-linux-x86_64-static.tar.gz)"

如果文件存在,则其完整路径将被分配给$the_file,否则将出现一个伪造的 glob 模式。

答案1

通配仅发生在列表上下文中,因此您需要分配给大批多变的。与ksh93, bash, zsh,mkshyash:

the_files=(~/downloads/stack-*-linux-x86_64-static.tar.gz)

或者在sh

set -- ~/downloads/stack-*-linux-x86_64-static.tar.gz

分配给$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

将会~扩大,但是不是全球。但是,如果您在扩展变量时忘记使用引号,如下所示:

printf '%s\n' $the_file # instead of printf '%s\n' "$the_file"

然后将内容$the_file进行 split+glob 并展开在那时候这可能会让您认为它有效,但实际上它不起作用,并且与波形符扩展相结合,它甚至会变得更加混乱。

例如,如果您的$HOMEis/All * Users/me$IFSis 设置为其默认值,$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))

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

the_files=(~/downloads/~(N)stack-*-linux-x86_64-static.tar.gz)

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

相关内容