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
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.
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.
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.
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.
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
.
Print the argument with echo
:
test=1 ls `if [ $test -eq 1 ]; then echo "-la"; fi` -R
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With