Bash 使用需要避免掉坑的地方
本文列出了五十多项在使用 Bash 的时候需要注意的地方,Bash 是如此强大但又非常容易出错,一不小心就会删干净你计算机中没备份的文件。如果说人在不停地试错中学习,本文给出了绝佳的避免犯错的清单。
- 通配符(*),空格( ), 有 leading-dash (-打头的文件), 有
!
是很多错误的本源。这些东西让 bash 很魔法,也很魔幻。每一行 sh 代码都要好好想想字符串或者变量中是否会存在被转义的可能,如果会,配置好环境变量或者加上 quote。- for i in 后面要用通配符 或者使用 find -exec.
- cp 的时候
"./$file"
这样比较靠谱。 [[ $var ==
[[
比较人性能识别$var
的空格[ "$var" =
[
就比较不人性了,得加"$var"
quote.- 很多人没有注意到
if [ a = b ]
的 if 后面有个空格,一定要注意啊,[
是个命令,不是高级语言的(
. echo "$foo"
会比echo $foo
更安全,万一$foo
里面有空格呢?a=b
才是正解,a="b"
是上上解,写成a = b
,a =b
,a= b
都是不对的- 交互模式下
echo "hello world\!"
才能避免!
被 histexpand, 或者干脆'hello world!'
或者加上set +H
~
只有在 token 的第一个字符才会被替换成 $HOME, 安全起见,还是写成$HOME
靠谱一些。
- 一些 shell 的语法长的和高级语言差不多,但其实不是
- 上面的
[
,[[
是一个例子 cmd1 && cmd2 || cmd3
<- 这个和 if (cmd1) then cmd2 else cmd fi 是不完全等价的,&& 会去看后面的命令是否返回 0,否则 cmd3 还是会被调用。function foo() { ... }
不一定都能工作啦,看你用什么 shell,但是foo() { ... }
都肯定可以移植运行成功的。read $foo
是错的,得写成IFS= read -r foo
, 尽管你取值的时候要用$foo
, 以及记得加quote 如果不安全的话。cat file | sed s/foo/bar/ > file
很多人都会一不小心写出来的东西:读文件,经过管道,写回文件,这只会让 file 的内容被清空。比较安全的做法是写到 tmpfile 在 mv 回来,或者对自己的 sed 技术够自信的话可以 edit in-place.cd /foo; bar
很多人都假定 bash 像高级语言一样,出错后崩溃就不往下执行了,并非如此。你要么得提前配置set -e
, 要么这里写成cd /foo && bar
, 或者cd /foo !! exit 1; bar
- 上面的
衍生思考:死ね,Bash!