Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Add command arguments using inline if-statement in bash

Tags:

bash

I'd like to add an argument to a command in bash only if a variable evaluates to a certain value. For example this works:

test=1 if [ "${test}" == 1 ]; then     ls -la -R else     ls -R    fi 

The problem with this approach is that I have to duplicate ls -R both when test is 1 or if it's something else. I'd prefer if I could write this in one line instead such as this (pseudo code that doesn't work):

ls (if ${test} == 1 then -la) -R 

I've tried the following but it doesn't work:

test=1 ls `if [ $test -eq 1 ]; then -la; fi` -R 

This gives me the following error:

./test.sh: line 3: -la: command not found 
like image 980
Johan Avatar asked Feb 23 '15 16:02

Johan


People also ask

How do I enter command line arguments in bash?

Shift operator in bash (syntactically shift n, where n is the number of positions to move) shifts the position of the command line arguments. The default value for n is one if not specified. The shift operator causes the indexing of the input to start from the shifted position.

How do you write an if statement in one line in bash?

If it is, then echo 1, otherwise echo 0. This is the command that I am using but it only works partially (more info below). Note that I need to write the script in one line. Note: The [s] in some_proces[s] is to prevent grep from returning itself.

How do you use multiple IF statements in shell script?

To use multiple conditions in one if-else block, then elif keyword is used in shell. If expression1 is true then it executes statement 1 and 2, and this process continues. If none of the condition is true then it processes else part.

What is in if condition in bash?

The if statement is composed of the if keyword, the conditional phrase, and the then keyword. The fi keyword is used at the end of the statement. The COMMANDS gets executed if the CONDITION evaluates to True. Nothing happens if CONDITION returns False; the COMMANDS are ignored.


2 Answers

A more idiomatic version of svlasov's answer:

ls $( (( test == 1 )) && printf %s '-la' ) -R 

Since echo understands a few options itself, it's safer to use printf %s to make sure that the text to print is not mistaken for an option.
Note that the command substitution must not be quoted here - which is fine in the case at hand, but calls for a more robust approach in general - see below.

However, in general, the more robust approach is to build up arguments in an array and pass it as a whole:

# Build up array of arguments... args=() (( test == 1 )) && args+=( '-la' ) args+=( '-R' )  # ... and pass it to `ls`. ls "${args[@]}" 

Update: The OP asks how to conditionally add an additional, variable-based argument to yield ls -R -la "$PWD". In that case, the array approach is a must: each argument must become its own array element, which is crucial for supporting arguments that may have embedded whitespace:

(( test == 1 )) && args+= ( '-la' "$PWD" ) # Add each argument as its own array element. 

As for why your command,

 ls `if [ $test -eq 1 ]; then -la; fi` -R 

didn't work:

A command between backticks (or its modern, nestable equivalent, $(...)) - a so-called command substitution - is executed just like any other shell command (albeit in a sub-shell) and the whole construct is replaced with the command's stdout output.

Thus, your command tries to execute the string -la, which fails. To send it to stdout, as is needed here, you must use a command such as echo or printf.

like image 139
mklement0 Avatar answered Sep 19 '22 08:09

mklement0


Print the argument with echo:

test=1 ls `if [ $test -eq 1 ]; then echo "-la"; fi` -R 
like image 35
svlasov Avatar answered Sep 22 '22 08:09

svlasov