The*_*eer 10 shell bash shell-script quoting wildcards
下面的例子解释了这个问题。为什么FILENAME在使用替换时回显并感知为模式时打印正确?
#!/bin/bash
FILEPATH_WITH_GLOB="/home/user/file_*"
FILENAME=$(basename "$FILEPATH_WITH_GLOB")
echo $FILENAME #file_1234
echo ${FILENAME:1:5} #ile_* <---why is this not ile_1
Run Code Online (Sandbox Code Playgroud)
Sté*_*las 15
Run Code Online (Sandbox Code Playgroud)FILEPATH_WITH_GLOB="/home/user/file_*"
现在,FILEPATH_WITH_GLOB包含/home/user/file_*
Run Code Online (Sandbox Code Playgroud)FILENAME=$(basename "$FILEPATH_WITH_GLOB")
FILENAME包含file_*.
Run Code Online (Sandbox Code Playgroud)echo $FILENAME #file_1234
$FILENAME在列表上下文中不加引号,该扩展经历 split+glob 运算符,因此扩展到匹配文件的列表:文件名生成在参数扩展时执行。
Run Code Online (Sandbox Code Playgroud)echo ${FILENAME:1:5} #ile_* <---why is this not ile_1
在列表上下文中它仍然是一个不带引号的参数扩展,所以仍然会经历 split+glob。但是在这里,ile_*模式不匹配任何文件,因此它会扩展到自身。
你可能想要的是:
shopt -s nullglob # have globs expand to nothing when they don't match
set -- /home/user/file_* # expand that pattern into the list of matching
# files in $1, $2...
for file do # loop over them
filename=$(basename -- "$file")
printf '%s\n' "$filename" "${filename:1:5}"
done
Run Code Online (Sandbox Code Playgroud)
或者您可以将它们存储在数组中:
shopt -s nullglob
files=(/home/user/file_*)
Run Code Online (Sandbox Code Playgroud)
如果您只关心第一个匹配项,或者您知道只有一个匹配项,则可以将该文件称为$files. bash具有通常令人讨厌的行为,而不是$files扩展到${files[0]}数组的所有元素(从 继承的行为ksh,固定在 中zsh),但在这里,这将是一次想要的行为。