Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Running multiple commands with bash without spawning subshells

Tags:

bash

cd folder &>/dev/null ||( mkdir folder && cd folder ) && git clone https://github.com/user/my-project.git

when running the above command I have the problem (I think), that the () spawns a subshell and runs the commands, then when running the git clone I'm not in the expected directory. Is there a way to run this line? My current solution is

cd folder &>/dev/null || mkdir folder && cd folder && git clone https://github.com/user/my-project.git

The thing is, I run cd folder twice even if the directory exists

like image 919
Rodrigo Kondo Avatar asked Mar 07 '23 04:03

Rodrigo Kondo


2 Answers

1. How to avoid spawning a subshell

There are two grouping operators in shell:

  • ( commands… ) Runs commands in a subshell
  • { commands… } Runs commands in the current execution environment.

But please be aware that ( and ) are shell meta-characters while { and } are not. The braces are reserved words, but only if they are complete words and appear as the first word in a command. So the braces need to be surrounded by spaces and the closing brace must come after a semi-colon. For a longer explanation, see Bash command groups: Why do curly braces require a semicolon?.

Specifically, you would have to write

cd folder &>/dev/null || { mkdir folder && cd folder; } && git clone https://github.com/user/my-project.git

Note the explicit semicolon to terminate the pipeline. You could have used it in the subshell compound command, too, but here you must use it.

However, you shouldn't really use this command, because it could fail if another process happened to create the directory folder after the first cd fails and before the mkdir runs. There is a better way:

2. How to make this command simpler and more robust

Because this is a very common task indeed, mkdir comes with the useful -p option (this option is required by Posix).

mkdir -p some/path

does two things differently:

  1. The intermediate directories are also created, if necessary

  2. No error is produced if the final directory already exists.

So the common idiom for tasks like this is:

mkdir -p folder && cd folder && git clone https://github.com/user/my-project.git

which would work even if folder were a complete path and more than one directory along the path needed to be added.

like image 188
rici Avatar answered Apr 08 '23 22:04

rici


The () does spawn a sub-shell. Here's an example of a one-line command that might be helpful:

if [ ! -d folder ]; then mkdir folder; fi; cd folder && git clone ...
like image 21
pcjr Avatar answered Apr 08 '23 21:04

pcjr