@故宫,琉璃瓦大红墙,巍巍峨峨在东方
shell编程是linux学习和维护中不可获取的一项技能,不管是通过交互的方式直接运行一行脚本,或者写成一个脚本文件等等,都可以使很多作业事半功倍,将重复性切类似性的Linux任务做成一个稳定shell也可以提高工作效率,降低人工成本。
1
在shell脚本编程的时候,一般都是以解释器语言的路径作为第一行的开始,如:
#!/bin/bash
#!/bin/python
#!/bin/awk
以上分别是告诉系统以bash、python、awk作为此脚本的解释器。
需要注意的是解释行是以#!为开头,而仅仅以#为开头的表示此行为注释。
那么如果第一行不指定解释器的话会怎样呢?答案就是会以当前所使用的shell作为解释器。
因此为了更好本规范以及告知系统当前脚本的解释器,第一行的必要性不言而喻。
2
最近在写脚本的时候一直沿用了自己所使用的sh也就是bash作为解释器,但是也一样延续了携带-f的习惯(忘记了是写哪个脚本的时候使用-f解决了某一个问题,所以就一直携带了😅)。
但是此次却因为-f引发了一系列的错误,也引起了自己对这个参数的重新审视和定义。
先说问题,以如下两个脚本为例,目的很简单就是列出以test为开头的文件:
[coreuser@HK-CentOS test]$ more 1.sh
#!/bin/sh -f
ls -l test*
[coreuser@HK-CentOS test]$ more 2.sh
#!/bin/sh
ls -l test*
以上两个脚本唯一的区别就是解释行是否携带了-f,但是结果却大相径庭:
[coreuser@HK-CentOS test]$ ls
1.sh 2.sh test1 test2 test3 what
[coreuser@HK-CentOS test]$ ./1.sh
ls: cannot access test*: No such file or directory
[coreuser@HK-CentOS test]$
[coreuser@HK-CentOS test]$ ./2.sh
-rw-rw-r--. 1 coreuser coreuser 0 Apr 6 22:08 test1
-rw-rw-r--. 1 coreuser coreuser 0 Apr 6 22:08 test2
-rw-rw-r--. 1 coreuser coreuser 0 Apr 6 22:08 test3
[coreuser@HK-CentOS test]$
可以看到脚本2才完美的达到了目的。
而脚本1却提示每一“test*”文件。
为什么会失之毫厘谬以千里呢?
原因可以通过使用man sh查看其的解释文档来看到如下的一行解释:
-f Disable pathname expansion.
所以一个小小的-f就导致了以上两个脚本的谬之千里的输出结果,因为sh中的-f直接屏蔽了*作为通配符的概念,而直接将其作为普通字符加入到了文件名中,所以脚本1才提示了“test*”不存在。
3
那么是不是所有的shell解释器都不能带-f呢?
我们再来看另外一个shell——csh的-f参数解析:
-f The shell does not load any resource or startup files, or perform any command hashing, and thus starts faster.
csh中的-f是在运行脚本的时候将不再查看用户配置等,将加快脚本的执行。
由此可见,也并不是所有的第一行都不能带-f,针对不同的解释shell做不同的处理才是正确之道。
以上。