zsh中file2与file3输出存在差异的原因解析
zsh脚本中file2与file3输出差异的原因解析
脚本与执行结果
脚本代码:
base="/VS/Harry Potter - Hedwig's Theme (Harmonica Ver.) [w2kuM-Rp_IY].info.json" echo "base: $base";; dir=$(dirname "$base"); filename=$(basename "$base"); file=${${filename%.*}%.*}; file2=${${"$(basename $filename)"%.*}%.*}; file3=${${$(basename $filename)%.*}%.*}; echo "file: $dir/$file";; echo "file2: $dir/$file2";; echo "file3: $dir/$file3";;
执行输出:
(base) ➜ Youtube zsh 1.sh base: /VS/Harry Potter - Hedwig's Theme (Harmonica Ver.) [w2kuM-Rp_IY].info.json file: /VS/Harry Potter - Hedwig's Theme (Harmonica Ver.) [w2kuM-Rp_IY] file2: /VS/Harry Potter - Hedwig's Theme (Harmonica Ver.) [w2kuM-Rp_IY] file3: /VS/Harry Potter - Hedwig's Theme (Harmonica Ver [w2kuM-Rp_IY]
差异原因
两者的核心区别在于命令替换是否被双引号包裹,以及zsh对无引号字符串的处理逻辑:
file2中,$(basename $filename)被双引号包裹,命令替换的结果会被当作单个完整字符串处理。哪怕$filename未加引号导致被分词,basename命令的输出最终被双引号整合为单一字符串,后续的%.*两次后缀截断操作都是针对整个文件名进行,因此得到正确结果。file3中,$(basename $filename)没有被双引号包裹,命令替换的输出会被zsh按空格拆分成多个独立的单词(数组元素)。此时${${...}%.*}会对数组中的每个单词单独执行后缀截断操作:- 原文件名中的
(Harmonica Ver.)被拆分为(Harmonica和Ver.)两个元素,Ver.)里的.)会被%.*匹配并截断,变成Ver; - 其他不含
.的单词保持不变; - 最后一个单词
[w2kuM-Rp_IY].info.json经过两次截断后得到[w2kuM-Rp_IY]; - 这些处理后的单词重新拼接,就得到了file3的异常输出。
- 原文件名中的
简单来说,file3因为缺少双引号,导致文件名被拆分成多个部分分别处理,最终出现截断错误。
内容的提问来源于stack exchange,提问作者Icec Winter
相关产品推荐
相关产品推荐

