119、【OS】【Nuttx】【周边】效果呈现方案解析:变量展开
【声明】本博客所有内容均为个人业余时间创作,所述技术案例均来自公开开源项目(如Github,Apache基金会),不涉及任何企业机密或未公开技术,如有侵权请联系删除
背景
接之前 blog
【OS】【Nuttx】【周边】效果呈现方案解析:作用域?
分析了一下 local 关键字和 POSIX 规范中的 Shell Execution Environment,下面继续分析
while 循环处理
继续看这条语句
local file_mtime=$(find "$dir" -name "*.html" -type f -printf '%T@' 2>/dev/null | sort -n | tail -1)
- find “$dir”:在变量 $dir 指定的目录中搜索,注意要加双引号
在 Shell 脚本中,对变量使用双引号是一个非常重要的细节,尤其在处理路径时,如果没有加双引号,可能有两个后果:
- 路径中含有空格或特殊字符时被错误拆分
- 通配符被意外展开
下面展开详细分析下
防止路径被错误拆分
假设变量 dir 的值中间有空格,终端输入
mkdir "test dir"
创建一个带空格的文件夹,这里也要加双引号,不然会被 mkdir 命令认为创建 test 和 dir 两个文件夹,终端输入
ls -d */
查看创建的 test dir 文件夹
-
ls -d :不要展开目录内容,只显示目录本身
-
*/ :glob 通配符模式,只匹配当前目录下的子目录
这里 ls 的输出中,test dir 被显示为 ‘test dir’(带单引号),是 ls 命令为了清晰显示特殊字符而做的视觉提示,明确表示这个文件名包含空格,避免用户误操作,比如以为是两个文件,在使用该文件夹名时同样也需要加引号,终端输入
cd "test dir"/
进入这个带空格的文件夹,接着输入
dir=$(pwd)
$() 在之前 blog 【OS】【Nuttx】【周边】效果呈现方案解析:-print0 补充(中) 讲过,是执行括号内的命令,并把命令的输出结果作为字符串返回,这里将 pwd 当前目录的路径返回出来并赋值给 dir 变量
此时如果执行
find $dir
不加双引号,结果如下
可以发现此时会被 Shell 解释为两个参数传递给 find 命令 /home/adminpc/nuttx_pdt/nuttx/scripts/test 和 dir, find 命令会认为此时要在两个目录中查找,显然是错误的
如果执行
find "$dir"
加上双引号,此时 Shell 会将整个路径作为一个完整的字符串传递给 find 命令
这样 find 命令就能正确识别这个包含空格的目录路径
防止通配符被意外展开
下面先看个例子,终端输入
mkdir important_dir1 important_dir2
创建两个文件夹,终端输入
dir=$(pwd)/important*
重新设置 dir,加入了通配符,此时如果输入
echo $dir
可以看到 Shell 已经查找当前目录下匹配这些名字的目录名,把通配符替换成实际的目录路径了
如果输入
echo "$dir"
可以看到双引号会抑制 Shell 的通配符展开,保护了变量内容,变量值中的 * 当作普通字符,原样传递给 echo 命令打印了出来
这里举的例子只是为了说明双引号对通配符的抑制作用,实际上,dir 就不应该包含通配符,因为从安全角度,变量应该被设置为具体的路径(值),而不是加入通配符
因为变量被设置后,再对变量引用时(一般是执行某个命令需要引用到该变量),为了防止变量被 IFS 拆分,需要将变量作为一个整体传递给命令,此时一般需要对变量加上双引号才进行引用
"$var"
前面分析了,双引号的加入会对通配符 * 进行抑制,此时通配符 * 将作为一个普通字符传递给命令,就达不到通配符本身的目的,而且由于变量包含普通字符 * 很可能会报错(路径或文件不存在)
另外,可以看到脚本里面实现的,通配符直接交给了 find 命令,而 dir 传入的是具体的路径值,也没有对通配符进行变量引用
ok,先到这里,下篇 blog 继续