Bash 脚本通配符不适用于现有文件
Bash script wildcard not working with existing file
我有一个脚本将带有通配符的 hdfs 文件路径分配给变量,但通配符不知何故不起作用。所以我写了这个测试脚本,在我的主目录
中创建了一个文件some-file.txt
FILEPATH=~/some*
echo $(ls $FILEPATH)
echo $FILEPATH
APPJAR=hdfs:///user/myusername/myproject/lib/myproject*.jar
echo $(hdfs dfs -ls $APPJAR)
echo $APPJAR
输出让我感到惊讶,因为前 3 行产生了我预期的结果,但 hdfs
行没有。
/home/myusername/some-file.txt
/home/myusername/some-file.txt
-rw-r--r-- 3 myusername supergroup 188267249 2018-04-19 23:20 hdfs:///user/myusername/myproject/lib/myproject-1.0.1-SNAPSHOT-f7b.jar
hdfs:///user/myusername/myproject/lib/myproject*.jar
显然,由于 hdfs dfs -ls
命令起作用,因此该文件存在于 HDFS 中。但是为什么 APPJAR
变量没有变成实际的文件名呢? hdfs命令有问题吗?
简单的答案是 Bash 不会自动感知像 HDFS 这样的任意协议。例如,您不会期望 https://example.org/*.txt
会扩展。如果您安装 HDFS 文件系统驱动程序并挂载该目录,它将正常完成。
这里的关键是 shell 不识别 hdfs:// URL;在那种情况下,我很确定扩展是由 hdfs
命令完成的(或者 not 完成,如果没有 hdfs
命令)。当 shell 看到 hdfs:///user/myusername/myproject/lib/myproject*.jar
时,它会查找名为 "hdfs:" 的目录(在当前工作目录下)(是的,“:”在文件名中是合法的),并且一个 "user" 子目录,等等。没有找到它们,它使通配符未展开。
我有几个一般性的建议:
不用echo $(somecommand)
,直接用运行命令即可。使用 $( )
捕获命令的输出,然后使用 echo
将其转回输出只会增加一层混乱。
使用set -x
使shell 在执行之前打印命令,这将让您看到扩展发生在哪里。例如,当您分配 FILEPATH=~/some*
时,您会看到 ~
在 分配完成之前扩展到主目录的路径 ,但是 *
直到后来才展开。
如果您不希望变量引用被拆分成单词并扩展嵌入的通配符,请在变量引用周围加上双引号。 echo "$variable"
将打印 $variable
的内容,而 echo $variable
将在打印前扩展通配符。
不要使用全部大写的变量名;改用小写或混合大小写。有大量具有特殊含义的全大写变量,如果您尝试将其中一个用于其他用途(例如 PATH
),您将遇到问题。
我有一个脚本将带有通配符的 hdfs 文件路径分配给变量,但通配符不知何故不起作用。所以我写了这个测试脚本,在我的主目录
中创建了一个文件some-file.txt
FILEPATH=~/some*
echo $(ls $FILEPATH)
echo $FILEPATH
APPJAR=hdfs:///user/myusername/myproject/lib/myproject*.jar
echo $(hdfs dfs -ls $APPJAR)
echo $APPJAR
输出让我感到惊讶,因为前 3 行产生了我预期的结果,但 hdfs
行没有。
/home/myusername/some-file.txt
/home/myusername/some-file.txt
-rw-r--r-- 3 myusername supergroup 188267249 2018-04-19 23:20 hdfs:///user/myusername/myproject/lib/myproject-1.0.1-SNAPSHOT-f7b.jar
hdfs:///user/myusername/myproject/lib/myproject*.jar
显然,由于 hdfs dfs -ls
命令起作用,因此该文件存在于 HDFS 中。但是为什么 APPJAR
变量没有变成实际的文件名呢? hdfs命令有问题吗?
简单的答案是 Bash 不会自动感知像 HDFS 这样的任意协议。例如,您不会期望 https://example.org/*.txt
会扩展。如果您安装 HDFS 文件系统驱动程序并挂载该目录,它将正常完成。
这里的关键是 shell 不识别 hdfs:// URL;在那种情况下,我很确定扩展是由 hdfs
命令完成的(或者 not 完成,如果没有 hdfs
命令)。当 shell 看到 hdfs:///user/myusername/myproject/lib/myproject*.jar
时,它会查找名为 "hdfs:" 的目录(在当前工作目录下)(是的,“:”在文件名中是合法的),并且一个 "user" 子目录,等等。没有找到它们,它使通配符未展开。
我有几个一般性的建议:
不用
echo $(somecommand)
,直接用运行命令即可。使用$( )
捕获命令的输出,然后使用echo
将其转回输出只会增加一层混乱。使用
set -x
使shell 在执行之前打印命令,这将让您看到扩展发生在哪里。例如,当您分配FILEPATH=~/some*
时,您会看到~
在 分配完成之前扩展到主目录的路径 ,但是*
直到后来才展开。如果您不希望变量引用被拆分成单词并扩展嵌入的通配符,请在变量引用周围加上双引号。
echo "$variable"
将打印$variable
的内容,而echo $variable
将在打印前扩展通配符。不要使用全部大写的变量名;改用小写或混合大小写。有大量具有特殊含义的全大写变量,如果您尝试将其中一个用于其他用途(例如
PATH
),您将遇到问题。