Linux
操作系统,抑或是
Windows
等操作系统上面,都会有命令行终端交互界面,当然
Linux
显然更加典型,也是更为熟悉的纯字符型界面交互。而在命令行进行系统操作时,自然需要使用一系列的命令,每个操作系统都有自己定义且认可的命令,否则,无法识别的命令操作系统往往会抛出错误,提示用户输入了无法识别的命令。
对像 Linux
这样的纯字符型会话的操作系统来说,脱离了像 Windows
更面向普通非计算机专业的家庭或者办公用户所提供的图形化的交互界面,此时用户必须敲入并且记住一系列,往往还携带了若干参数的命令,来完成在图形化界面上只需要通过点点点即可完成的一系列操作,例如切换至某个目录 cd(change directory):
cd /some-directory
查看一下当前目录下面有哪些文件:
ls /some-directory
将某个文件移动到另外一个目录下面:
mv some-file.file /another/directory/you-can-rename-your-file.file
复制:
cp some-file.file /target/directory/you-can-rename-your-file-as-well.file
从用户常用的简单的文件操作来看,Linux
上显然不太方便,但是,当涉及到文件的批量处理的时候,命令行提供了 管道编程 以及各种基于 正则表达式 的方式,结合字符串处理,可以非常高效灵活的实现文件的批量处理,比如将文件批量按照一定格式重命名,批量添加后缀等。。。
像这样较为复杂,但确建立在一定的规则之上的批量任务,往往借助编程语言,通过编程的方式可以快速提供一个解决方案,在 Linux
上,这样的解决方案就是 Shell
脚本,本质上即是一系列 Shell
命令的文本,执行该文件即是逐行执行其中的 Shell
命令。
而在脚本当中,相比于直接在交互式的命令行上,最大的区别就在于:
- 变量
- 控制语句,比如常见的
if
for
等
通过引入了变量和控制语句,使得脚本执行时可以覆盖更多的逻辑,以及执行结果的引用,即可以在脚本中引用某条命令的执行结果,还可以根据执行结果判断后续进行什么样的操作,使得一些我们常用的一系列复杂操作或者经验可以固化下来,一键批量完成任务。
变量
Shell
变量赋值与大多数的编程语言一样:
text="here is a string"
可以直接赋值,但是 =
两边不能带有空格,另外,需要加上 $
符号才可以进行变量引用:
# 引用前文声明的变量
echo $text
echo ${text}
echo '${text}'
上面三种方式,都可以得到输出:'here is a string'
,不同之处在于,某些情况为了避免歧义,通过 {}
可以让 Linux
明确知道,大括号内即为引用的变量命令。而最后一种方式,意味着可以在字符串中引入变量值,即:
echo 'Look, ${text} !'
输出结果为 'Look, here is a string !'
,通过这种方式,可以实现字符串的拼接以及格式化输出。
也可以将命令的输出内容保存到变量中:
files=`ls /tmp`
``````中可以执行命令,并且返回结果将会保存在变量中,而目录中往往不止一个文件,因此,变量 files
为一个列表,可以通过循环的方式对列表的内容进行遍历:
for f in $files
do
echo $f
done
上述脚本将会逐行打印出 files
中的每一个文件名,这种方式可以用于批量处理某类文件的操作,例如将 xls
的文件批量转为 xlsx
的文件:
# 获取目录下面所有 .xls 文件 (2003版 excel)
xlsList=`ls *.xls`
# 批量重命名
for x in xlsList
do
# %. 表示右边开始第一个 .
# %% 表示右边开始最后一个
# #. 表示左边开始第一个
# ## 表示左边开始最后一个
# * 表示删除内容,在 . 右边表示删除右边的所有内容
# ${x%.*} 即为不带后缀的文件名称
mv $x ${x%.*}.xlsx
done
上述脚本可以实现批量的后缀转换。
此外,还有一些较为特殊的变量,可以在 Shell
脚本中直接使用,每个变量都有相应的使用场景,比如:
- 你可能需要判断刚刚执行完成的命令是否成功,来确定接下来程序的执行内容
此时,判断语句中必然涉及到相应的逻辑表达式,表达式中自然包含了参与判断的变量。根据编程经验,你可能马上会想到这样的方法:
result=(`mkdir a-new-directory`)
# if .... then .... 利用 $result 变量值进行逻辑判断
但是如果前文介绍的内容足够清晰,那么显然这种方式得到的是 输出结果 而不是 执行结果,每条命令根据其定义,会有各种各样各不相同的输出,但是执行结果往往只会有两种,即 1
或者是 0
,成功与否而已。
例如:
echo "This is output"
此时上述程序输出内容显然即为 echo
的内容,而只要用户填入了正确的字符串,那么上述命令执行结果永远成功,但是输出内容则是千变万化。
放心,Linux
自然提供了获取执行结果的方式:
mkdir new-directory
if[[ $? -eq 0 ]]; then
echo "Make new directory successfully!"
fi
从判断语句内的输出可以猜到,$?
即为 mkdir
的执行结果,表达式中 eq
即为 ==
相等的判断。对于几乎所有命令来说,当且仅当 $? eq 0
,即执行返回值为 0
时,命令执行成功,而 $?
表示的是:最近一条命令的执行结果。
因此,在每条命令执行完成之后,都可以通过变量 $?
来得到执行结果,当然如果后续需要根据多条命令的执行结果进行判断的话,则需要通过引入变量来保存每条命令的执行结果了:
# Linux command one
result_one=$?
# Linux command two
result_two=$?
# ...
控制语句
if [[ $? -eq 0 ]]; then
# do sth
fi