357

I am trying to merge multiple linux commands in one line to perform deployment operation. For example

cd /my_folder
rm *.jar
svn co path to repo
mvn compile package install

11 Answers 11

772

If you want to execute each command only if the previous one succeeded, then combine them using the && operator:

cd /my_folder && rm *.jar && svn co path to repo && mvn compile package install

If one of the commands fails, then all other commands following it won't be executed.

If you want to execute all commands regardless of whether the previous ones failed or not, separate them with semicolons:

cd /my_folder; rm *.jar; svn co path to repo; mvn compile package install

In your case, I think you want the first case where execution of the next command depends on the success of the previous one.

You can also put all commands in a script and execute that instead:

#! /bin/sh

cd /my_folder \
&& rm *.jar \
&& svn co path to repo \
&& mvn compile package install

The backslashes at the end of the line are there to prevent the shell from thinking that the next line is a new command; if you omit the backslashes, you would need to write the whole command in a single line.

A more convenient way compared to using backslashes and && everywhere is to instruct the shell to exit the script if any of the commands fail. You do that using the set built-in function with the -e argument. With that, you can write a script in a much more natural way:

#! /bin/sh
set -e

cd /my_folder
rm *.jar
svn co path to repo
mvn compile package install

Save that to a file, for example myscript, and make it executable:

chmod +x myscript

You can now execute that script like other programs on the machine. But if you don't place it inside a directory listed in your PATH environment variable (for example /usr/local/bin, or on some Linux distributions ~/bin), then you will need to specify the path to that script. If it's in the current directory, you execute it with:

./myscript

The commands in the script work the same way as the commands in the first example; the next command only executes if the previous one succeeded. For unconditional execution of all commands, simply don't call set -e:

#! /bin/sh

cd /my_folder
rm *.jar
svn co path to repo
mvn compile package install
5
  • 48
    For future readers: You can also use || instead of semicolon or && if you only want the next command to be executed if the last one failed. As in try this, and if it fails, try that.
    – DeVadder
    Commented May 7, 2014 at 14:55
  • 3
    Hm, semicolons not always works. E.g. ls >/dev/null & ; echo $! triggers an error.
    – Hi-Angel
    Commented Nov 6, 2014 at 8:52
  • 2
    And what if I want to run first command in background and another in foreground.. I am trying this tail -f my.log & && ./myscript which is not working.. please suggest.
    – Paresh
    Commented Jun 4, 2015 at 4:32
  • 4
    @Pareshkumar With bash, you can do: { tail -f my.log & } && ./myscript However, note that the && is useless here, since the first job runs in the background and thus the second job can't know the result, since both jobs will start at the same time. So you might as well just write: { tail -f my.log & }; ./myscript
    – Nikos C.
    Commented Jun 4, 2015 at 9:08
  • 1
    What if I need sudo permissions to run one of the commands? Should i put the sudo at the beggining of all the commands or just in the one that needs it? How can I pass the password to that command so it is properly executed?
    – Drubio
    Commented Jan 11, 2019 at 18:01
50

I've found that using ; to separate commands only works in the foreground. eg :

cmd1; cmd2; cmd3 & - will only execute cmd3 in the background, whereas cmd1 && cmd2 && cmd3 & - will execute the entire chain in the background IF there are no errors.

To cater for unconditional execution, using parenthesis solves this :

(cmd1; cmd2; cmd3) & - will execute the chain of commands in the background, even if any step fails.

3
  • 3
    Was the trailing ampersand (&) in your examples intentional? If so, what is it for? Commented Nov 19, 2015 at 17:22
  • 8
    @Technophile It's to run a background command Commented Apr 7, 2016 at 17:54
  • 2
    One simple, short and direct answer, you should use StackExchange websites more often Dean. Thanks for your input.
    – CPHPython
    Commented Oct 4, 2016 at 13:22
10

You can separate your commands using a semi colon:

cd /my_folder;rm *.jar;svn co path to repo;mvn compile package install

Was that what you mean?

2
cd /my_folder && rm *.jar && svn co path to repo && mvn compile package install
4
  • it's not the same as the OP script, please explain : if a a command fails, the script abort Commented Oct 25, 2012 at 21:06
  • 5
    Additionally, you can use cmd1 || cmd2 separator if you need cmd2 to execute only if cmd1 returned non-zero status to shell, and you may use cmd1 ; cmd2 if you want to run both commands irrespective of their return status. Commented Oct 25, 2012 at 21:08
  • @sputnick It should be, I just pasted it in and concatenated the commands with && Commented Oct 25, 2012 at 21:08
  • 3
    @MarkStevens It's a better implementation but it won't get to the same results as if the commands were run sequentially, I think that's what sputnick meant.
    – andrux
    Commented Oct 25, 2012 at 21:11
2

To run them all at once, you can use the pipe line key "|" like so:

$ cd /my_folder | rm *.jar | svn co path to repo | mvn compile package install
2
  • 5
    The pipeline is being used to give the output of your command to the next command as an input. For example : X | Y --> X command output will work as input for Y command Commented Oct 17, 2018 at 3:57
  • 1
    Using pipe is not the same as putting commands in a single line. For example, cd Downloads/ | ls is not the same as cd Downloads/ && ls Commented Jan 1 at 4:45
1

If you want to execute all the commands, whether the previous one executes or not, you can use semicolon (;) to separate the commands.

cd /my_folder; rm *.jar; svn co path to repo; mvn compile package install

If you want to execute the next command only if the previous command succeeds, then you can use && to separate the commands.

cd /my_folder && rm *.jar && svn co path to repo && mvn compile package install

In your case, the execution of consecutive commands seems to depend upon the previous commands, so use the second example i.e. use && to join the commands.

1

What is the utility of an only one Ampersand? This morning, I made a launcher in the XFCE panel (in Manjaro+XFCE) to launch 2 passwords managers simultaneously:

sh -c "keepassx && password-gorilla"
or
sh -c "keepassx; password-gorilla"

But it does not work as I want. I.E., the first app starts but the second starts only when the previous is closed

However, I found that (with only one ampersand):

sh -c "keepassx & password-gorilla"

and it works as I want now...

1
  • 1
    Ampersand acts as command terminator similar to ;, except that this puts comman before it in background, i.e. shell won't see its output. Commented May 27, 2018 at 2:04
0
  1. Use ;
  • No matter the first command cmd1 run successfully or not, always run the second command cmd2:
    • $ cd myfolder; ls # no matter cd to myfolder successfully, run ls
  1. Use &&
  • Only when the first command cmd1 run successfully, run the second command cmd2:

    • $ cd myfolder && ls # run ls only after cd to myfolder
  1. Use ||
  • Only when the first command cmd1 failed to run, run the second command cmd2:

    • $ cd myfolder || ls # if failed cd to myfolder, `ls` will run
-1

You can use as the following code;

cd /my_folder && \
rm *.jar && \
svn co path to repo && \
mvn compile package install

It works...

-1

I find lots of answer for this kind of question misleading

Modified from this post: https://www.webmasterworld.com/linux/3613813.htm

The following code will create bash window and works exactly as a bash window. Hope this helps. Too many wrong/not-working answers out there...

            Process proc;
            try {
                //create a bash window
                proc = Runtime.getRuntime().exec("/bin/bash");
                if (proc != null) {
                       BufferedReader in = new BufferedReader(new InputStreamReader(proc.getInputStream()));
                       PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(proc.getOutputStream())), true);
                       BufferedReader err = new BufferedReader(new InputStreamReader(
                       proc.getErrorStream()));
                       //input into the bash window
                       out.println("cd /my_folder");
                       out.println("rm *.jar");
                       out.println("svn co path to repo");
                       out.println("mvn compile package install");
                       out.println("exit");
                       String line;
                        System.out.println("----printing output-----");
                          while ((line = in.readLine()) != null) {
                             System.out.println(line);
                          }
                          while((line = err.readLine()) != null) {
                             //read errors
                          }
                          proc.waitFor();
                          in.close();
                          out.close();
                          err.close();
                          proc.destroy();
                }

            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
-1

FYI, if you need to run multiple commands in one-line in if-else, you can group the commands with parenthesis. See this page for more details.

You can replace the semicolon (;) with && or || depending on what you need. Please note that parenthesis creates a sub-shell to execute the commands.

Following command executes the cmd1, cmd2, and cmd3 commands if a file called file_name exists; otherwise, cmd4, cmd5, and cmd6.

[ -f file_name ] && (cmd1; cmd2; cmd3) || (cmd4; cmd5; cmd6)

Not the answer you're looking for? Browse other questions tagged or ask your own question.