是否有可靠的方法利用路径名扩展将文件名分配给变量?
这可行,但看起来有点狡猾:
the_file="$(echo ~/downloads/stack-*-linux-x86_64-static.tar.gz)"
如果文件存在,则其完整路径将被分配给$the_file
,否则将出现一个伪造的 glob 模式。
答案1
通配仅发生在列表上下文中,因此您需要分配给大批多变的。与ksh93
, bash
, zsh
,mksh
或yash
:
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 zsh
or yash
(或只是$the_files[1]
in zsh
)或"${the_files[0]}"
in ksh
or bash
。
对于所有元素:("${the_files[@]}"
也在$the_files
中zsh
)。
$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 并展开在那时候这可能会让您认为它有效,但实际上它不起作用,并且与波形符扩展相结合,它甚至会变得更加混乱。
例如,如果您的$HOME
is/All * Users/me
和$IFS
is 设置为其默认值,$the_file
则将包含/All * Users/me/downloads/stack-*-linux-x86_64-static.tar.gz
并printf
打印/All
,后跟当前目录中的所有文件名( 的扩展*
),然后是Users/me/downloads/stack-*-linux-x86_64-static.tar.gz
.
如果模式与任何文件都不匹配怎么办
在 中zsh
,您会收到错误,但在其他 shell 中,模式保持不变。最好的情况是该模式完全不扩展。
使用zsh
,即使用N
glob 限定符:
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 nullglob
in bash
、set -o nullglob
in yash
)。