最新消息:

shell命令连接符(翻译)

shell 大步 1901浏览 0评论

 

Command chaining

作用:

提高效率

某些情况下减少系统资源占用

减少代码量

 

 

& –后台运行命令(所以可以同时多个进程多个命令)
; –顺序执行多个命令
\ –将一行很长的命令分成几行输入
&& –逻辑与操作符
|| –逻辑或操作符
! -逻辑非操作符 ( Thanks for mgd@interbaun.com for giving good examples)
| — 管道命令符
{} –命令组合操作符
() –优先操作符

 

 

预备知识:

Exit status 

对于 *NIX 系统而言,每一条命令,不管是内置的,SHELL 函数还是外置的,当它退出时,都 会返回一个小整数给引用它的程序,这就是程序退出状态 ( exit status ).

一般来讲,退出状态 0 表示正常执行,没有遭遇任何问题。其他非零的状态码均表示失败。与 没有布尔值版本的C语言不同,C语言中是非0为真,0为假。

在 shell 中,可以使用 $? 来访问最后一个程序的退出状态。

下面是 POSIX 的结束状态:

退出状态码 含义
0 命令成功退出
> 0 在重定向或者单词展开期间(~、变量、命令、算术展开以及单词切割)失败。
1 – 125 命令不成功退出。特定的退出值的含义,有各个命令自行定义。
126 命令找到了,但是文件无法执行。
127 命令没有找到
> 128 命令因收到信号而死亡。

POSIX 没有定义 128 的状态码,仅要求它表示某种错误。因为只有低位的 8 个位会返回给父进程,因此,所有大于 255 的退出状态都会被对 256 取模,然后将其结果作为实际的 exit status code.

在 shell 脚本中,可以使用 exit integer_value 这种方式声明退出状态。如果没有显式地声明,则会以最后一个程序的退出状态作为当前脚本的退出状态。也可以使用 exit $? 来表示。

 

来源: <http://www.fising.cn/2011/08/%E5%85%B3%E4%BA%8E-unix-linux-%E7%A8%8B%E5%BA%8F%E9%80%80%E5%87%BA%E7%8A%B6%E6%80%81-exit-status.shtml>

 

 

 

符号&  ;    &&  区别

 

command1 & command2 & command3     三个命令同时执行(后台执行)  shell后台运行(同时运行)多个命令行

command1; command2; command3    从前到后逐次进行,只有当前面的命令执行完成后(注意:这里指的完成包括即使命令出错,也算是完成的一种),才会执行后面的命令。

command1 && command2             只有前面命令执行成功,后面命令才继续执行

 

 

竖线(|)——管道符号

 

管道符号,是unix功能强大的一个地方,符号是一条竖线:"|",用法: command 1 | command 2 他的功能是把第一个命令command 1执行的结果作为command 2的输入传给command 2,例如:

 

$ls -s|sort -nr|pg

该命令列出当前目录中的任何文档,并把输出送给sort命令作为输入,sort命令按数字递减的顺序把ls的输出排序。然后把排序后的 内容传送给pg命令,pg命令在显示器上显示sort命令排序后的内容。

 

 

& –后台运行命令(所以可以同时多个进程多个命令)

 

这个操作符可以将进程/脚本/命令放到后台执行,因此我们可以继续在前台执行其他的命令,从而提供充分利用系统资源,加速脚本的运行。这个过程在其他的编程语言中也被称为创建子进程或者是forking。

 

例子1:后台运行命令

$ping -c1 google.com &

例子2: 后台同时运行多个命令

ping -c1 google.com & scp root@1.1.1.10:/opt/* /opt &

上面的命令是在后台各自独立运行的,所以我们可以使用这个操作符来同时运行多个命令。

 

; –顺序执行多个命令

将多个命令连在一起,按顺序执行,只有前面的命令完成(错误也是完成的一种),后面的命令才执行。一般都是用来在一行中写多个命令。

例子3: 在一行中顺序执行ls、pwd、whoami三个命令

ls;pwd;whoami

Note: 一行中可以通过 ; 来连接多少个命令,这个限制由内存或者ulimits来设定的。

例子4: 在shell脚本中,用一行来写完整个if语句。

if [ $? -eq 0 ]; then echo "success'; else echo "fail"; fi

例子5: 一行写完整个for语句

for i in *;do echo "file is $i";done

例子6:一行写完整个while语句

while [ $VAR1 -eq 10 ]; do echo "Var value is $VAR1"; done

例子7:一行写完整个until语句

until [ $VAR1 -eq 10 ]; do echo "Var value is $VAR1"; done

这个命令符主要是为了在终端中临时的直接执行脚本命令,而不用先写入到shell脚本文件,然后在执行。

 

\ – 连接符

这个操作符是为了将一行很长的命令分成几行输入。比如在编译软件时候,编译的参数太长太多,为了方便阅读,就会使用这个操作符。还有比如,文件路径作为参数时候,路径太长,这时候如果都放在一行,那么明显会难以阅读,此时我们也可以分多行输入。

Example8: 尝试从 sysloggerserver1.linuxnix.com 复制文件/var/ftp/pub/webadmin/debina/read 到 sysloggerserver2.persistentsystems.co.in上的/opt/oradba/debadmin/logic/abc文件夹

ssh abc@sysloggerserver1.linuxnix.com: \
 /var/ftp/pub/webadmin/debian/read \
 abc@sysloggerserver2.persistent.co.in\
:/opt/oradba/debadmin/logic/abc/

这样分多行输入,明显就更容易阅读和理解。

'&&' –与操作符

这个操作符保证只有第一个命令成功(即exit status 为0)的时候,才会去执行第二条命令。

注意成功与完成的区别:假设第一条命令出错了,那么肯定是不成功的,但是却是完成的。所以,当是 command 1 ; command2  ,则命令1出错的时候,命令2依旧可以执行。而如果换成了command 1 && command2 ,则命令1出错的时候,命令2肯定不会执行。

 

例子9: 只有当ping通主机后才ssh登录该主机

ping -c1 abc.com && ssh abc@abc.com

例子10: 只有当变量未赋值时,才将一个值赋给它

[ -z $VAR1 ] && VAR1=10

例子11: 检测一个文件夹是否存在,不存在则创建它

[ ! -d /var/temp ] && mkdir /var/temp

例子12: 只有当目录创建成功后,才切换到创建的目录

mkdir abc && cd abc

例子13:只有切换到目录成功后,才列出目录内容

cd /var/ftp && ls

可以用该操作符节省时间

|| –或操作符

这个操作符表示当第一条命令失败(即exit status 为非0 ,命令出错结果也是非0的,表明是失败的)的时候,才执行第二条命令。该操作符主要是用来检测失败的状态。

 

例子14: 当文件夹不存在的时候,才创建它,可以对比下例子11

[ -d /var/temp ] || mkdir /var/temp

例子15: ping一台主机,当无法ping同的时候,告诉用户网络未连通

ping -c1 google.com &> /dev/null || echo "There is some problem with network, please connect your network admin"

&& and || 操作符组合使用

我们可以同时用&& 和 || 来在一行代码中模拟 if-else语句. 如果第一条语句成功,则执行第二条语句,否则执行第三条语句

例子16: ping google.com, 成功和失败分别打印不同的信息

ping -c1 google.com && echo "That's good, able to ping google.com" || echo "That's bad unable to ping google.com"

例子17: 检测文件是否存在,存在则告诉用户,不存在则创建该文件

[ -f /var/abc.txt ] && echo "file exists" || touch /var/abc.txt

例子18: 检测上个pwd命令的执行结果

[ $? -eq 0 ] && echo “Yes, pwd command successfully executed” || echo “pwd command failed”

! -非操作符

该操作符主要用于排除某个文件。尤其当你删除或移动文件的时候,除了某类文件外,其他的都删除,这时候就可以使用该操作符了

例子19: 除了.doc文件外,其他后缀的文件全删除

ls | grep -v doc | xargs rm -rf or rm -rf *.{xls, txt, pdf}

如果不使用非操作符,那么需要四个命令完成上面的操作。如果使用非操作符,可以极大的减少代码量:

rm !(*.doc)

Note: 如果上面的命令无效,则需要用shopt命令,允许 glob 选项。

例子20: 除了.doc文件外,其他文件全都移动到/opt目录

mv !(*.doc) /opt/

例子21:除了.pdf文件外,拷贝其他文件到/opt/all目录

cp !(*.pdf) /opt/all 

| — 管道操作符

将第一条命令的输出结果,作为第二条命令的输入.

例子22: 计算当前文件夹下的文件和文件夹数目

ls -l | wc -l

例子23: 打印系统所有分区的名字

df -h | awk '{print $1}'

{ } –命令组合操作符

该操作符将多个命令组合在一起。见下面的例子:

例子24: 检查/opt/abc.txt 是否存在,不存在,则打印"The file does not exist",同时创建该文件

[ -f /opt/abc.txt ] || echo “The file does not exist”; touch /opt/abc.txt

如果按照上面的写法,则 touch命令的执行并不会由第一条命令的执行结果决定,无论第一条命令是否执行成功,touch命令都会执行,这显然和我们的要求不符合,所以此时就需要用到组合操作符了。

[ -f /opt/abc.txt ] || { echo "The file does not exist"; touch /opt/abc.txt; }

Note: 千万要记得最后两个命令之间的 “;”,以及花括号周围的空格,否则会报错

例子25: Ping一台主机,如果成功,则打印成功信息,并且ssh登录.

ping -c www.linuxnix.com && {echo “That is ping-able, too good..!”; ssh root@www.linuxnix.com;}

() –优先操作符

该操作符可以让某条命令优先执行。见下面的例子:

command1 && command2 || command3 && command4

如果命令1和命令2都执行成功,则命令3和命令4都不会执行。所以,我们要加上优先操作符,确保当命令1或者命令2任意一条执行失败的时候,命令3和命令4都会执行,修改后的如下:

例子26:

( command1 && command2 ) || ( command3 && command4 )

 

简要描述

shell_command_chaining

翻译自: <http://www.linuxnix.com/2012/07/23-awesome-less-known-linuxunix-command-chaining-examples.html>

 

 

转载请注明:大步's Blog » shell命令连接符(翻译)

SiteMap