同时执行多条命令


使用;、&&、||执行多条命令

回到顶部

shell下可以同时输入多条命令,命令之间用()隔开,shell会按照顺序执行命令。如果命令超过了一行,也可以用反斜杠(\)将命令接到下一行。 如果要同时执行多条命令,可以将要执行的命令集合写入shell script文件,也可以通过;、&&或||在命令行中一次执行多条命令。
1.连续执行两条命令:

              [root@initroot ~]# cmd1 ; cmd2
            
命令cmd1执行完毕后就会执行cmd2,分号(;)前后的两个命令可以没有任何关联。
2.只有cmd1执行成功($?=0)才会执行cmd2;若cmd1执行出错($?≠0),则cmd2不执行:
              [root@initroot ~]# cmd1 && cmd2
            
3.只有cmd1执行出错($?≠0),才会执行cmd2;若cmd1执行成功($?=0),则cmd2不执行:
              [root@initroot ~]# cmd1 || cmd2
            
变量$?为最近一次命令执行的返回值,通过变量$?可以判断命令执行是否成功,若命令执行成功,则$?=0,如果命令执行出错,则$?!=0。 && 或 ||通过判断$?来决定后续的命令是否执行。
              [root@initroot ~]# ls /tmp/initroot
              ls: cannot access '/tmp/initroot': No such file or directory
              [root@initroot ~]# echo $?
              2
              #ls /tmp/initroot的返回值为2,说明该条命令没有执行成功
              [root@initroot ~]# cd /home/peter/
              [root@initroot ~]# echo $?
              0
              #cd /home/peter/的返回值为0,说明该条命令执行成功
            
以下是相关的例子:
1.在关机的时候希望可以先执行两次sync,将数据同步写入磁盘后再shutdown计算机:
              [root@initroot ~]# sync; sync; shutdown -h now
              #命令之间用分号(;)隔开,分号前的命令执行完后就会立刻执行后面的命令。
            
2.在某个目录下建立一个文件,需要先判断目录是否存在,只有在目录存在的情况下才建立文件。
除了使用shell判断式(test)判断目录是否存在,也可以使用ls命令执行的返回值来判断目录是否存在:
              #使用ls检查目录/tmp/initroot是否存在,若存在则用touch建立/tmp/initroot/haha
              [peter@study ~]$ ls /tmp/initroot && touch /tmp/initroot/haha
              ls: cannot access /tmp/initroot: No such file or directory
              #ls命令和touch命令的执行具有相关性,前一个命令执行成功才会执行后一个命令!
              #ls提示找不到该目录,说明执行失败,后续的touch不会执行
            
手动建立/tmp/initroot目录后再次运行刚才的命令:
              [peter@study ~]$ mkdir /tmp/initroot
              [peter@study ~]$ ls /tmp/initroot && touch /tmp/initroot/haha
              [peter@study ~]$ ll /tmp/initroot
              -rw-rw-r--. 1 peter peter 0 Jul 9 19:16 haha
              #如果/tmp/initroot不存在,touch就不会被执行,若/tmp/initroot存在,touch就会执行!
            
3.上面的例子需要手动建立/tmp/initroot目录,下面的例子通过ls判断/tmp/initroot是否存在,若不存在则建立:
              #先删除/tmp/initroot目录,方便后续操作
              [peter@study ~]$ rm -r /tmp/initroot
              [peter@study ~]$ ls /tmp/initroot || mkdir /tmp/initroot
              ls: cannot access /tmp/initroot: No such file or directory
              [peter@study ~]$ ll -d /tmp/initroot
              drwxrwxr-x. 2 peter peter 6 Jul 9 19:17 /tmp/initroot
            
即使重复执行ls /tmp/initroot || mkdir /tmp/initroot也不会出现重复mkdir的问题!因为再次执行的时候/tmp/initroot已经存在, 所以后续的mkdir就不会执行!
4.判断/tmp/initroot目录是否存在,如果存在则建立/tmp/initroot/haha文件,如果/tmp/initroot目录不存在, 则先建立/tmp/initroot目录后再建立/tmp/ainitroot/haha文件:
              [peter@study ~]$ ls /tmp/initroot || mkdir /tmp/initroot && touch /tmp/initroot/haha
            
上述命令无论/tmp/initroot目录是否存在,/tmp/initroot/haha文件都会被成功建立。执行逻辑如下:
(1)如果/tmp/initroot不存在,ls执行失败,返回$?≠0,||判断$?≠0,则执行mkdir /tmp/initroot。 mkdir /tmp/initroot成功执行,mkdir返回$?=0,&&判断$?=0,执行touch /tmp/initroot/haha,最终haha成功建立;
(2)如果/tmp/initroot存在,ls执行成功,返回$?=0,||判断$?=0,不会执行mkdir /tmp/initroot。 此时$?=0会继续传递给&&,&&判断$?=0,则执行touch /tmp/initroot/haha,最终haha成功建立。
5.通过ls判断/tmp/initroot目录是否存在,若存在则显示"exist",若不存在,则显示"not exist":
              [peter@study ~]$ ls /tmp/initroot && echo "exist" || echo "not exist"
              #如果ls /tmp/initroot执行成功,则执行echo "exist",若执行失败则执行echo "not exist" !
            
如果写成如下形式会有问题吗?
              [peter@study ~]$ ls /tmp/initroot || echo "not exist" && echo "exist"
            
上面的写法是有问题的,执行逻辑如下:
1) 如果/tmp/initroot存在,则ls执行成功,返回$?=0,||判断$?=0,不执行echo "not exist"。$?=0继续传递给&&,&&判断$?=0,则执行echo "exist";
2) 如果/tmp/initroot不存在,则ls执行失败,返回$?≠0,||判断$?≠0,则执行echo "not exist",echo "not exist"执行成功,返回$?=0并传递给后面的&&。 &&判断$?=0,则执行echo "exist"。
所以上述命令执行完后,如果/tmp/initroot存在,则输出exist,如果不存在,则会同时输出not exist和exist。 这个结果显然是不正确的,所以在使用&&和||执行多条命令的时候,一定要仔细屡清楚命令的执行逻辑!

initroot编辑整理,转载请注明www.initroot.com

100次点赞 100次阅读