Reputation: 2521
I would like to have the equivelant of the following in a one line if/else condition.
$maxline=`cat journald.conf | grep "#SystemMaxUse="`
if [ $maxline == "#SystemMaxUse=" ]
then
sed 's/\#SystemMaxUse=/SystemMaxUse=50M/g' journald.conf > journald.conf2
mv journald.conf2 journald.conf;
else
echo "This file has been edited. You'll need to do it manually."
fi
I'm attempting to put this into a one line command. So far I've gotten it all but the else portion of the command. Here's what I have so far...
maxline=`cat journald.conf | grep "#SystemMaxUse="` && if [ $maxline == "#SystemMaxUse=" ]; then sed 's/\#SystemMaxUse=/SystemMaxUse=50M/g' journald.conf > journald.conf2 && mv journald.conf2 journald.conf; fi
So how can I include the else portion of the above code into my command? Thank you for your help in advance.
Upvotes: 87
Views: 226943
Reputation: 7277
Nice alternative to if/then/else
is this construction:
[[ test_expression ]] && code_if_ok || code_if_fail
It's perfectly suits for some simple cases. Here is an example:
$ true && echo ok || echo fail
ok
$ false && echo ok || echo fail
fail
But there is a catch if code_if_ok
failed for some reason code_if_fail
will also be executed but in most cases that's not what we expect, check this out:
$ true && { echo ok; false;} || echo fail
ok
fail
Of course this could be workarounded like this:
$ true && { echo ok; false; true;} || echo fail
ok
We put true
command at the and of our code_if_ok
part to make it end with 0 exit code and prevent code_if_fail
part to start. So your code could be rewritten like this:
grep -q '#var=' f && { sed 's|#\(var=\).*|\1val|g' f > f2; mv f{2,}; true;} || echo 'file edited'
Upvotes: 5
Reputation: 31
I recently saw the following. example, if you are not root make $var with a value
[[ $(id -u) -ne 0 ]] && var='you are not root user'
Upvotes: 2
Reputation: 21
The others answered your question, but not your specific situation. You've got cat going into grep going into a variable before we even get to the question; what you're really asking is 'how to conditionally edit a file'.
You could do this all in sed, either with some bash:
sed -n '/^#SystemMaxUse=$/Q1' journald.conf && echo "This file has been edited. You'll need to do it manually." || sed -i 's/^#\(SystemMaxUse=\)$/\150M/' journald.conf
or no bash:
sed -ni journald.conf -e 'H;${x;s/^#\(SystemMaxUse=\)$/\150M/m;ta;s/\n\(.*\)/\1/p;s/.*/This file has been edited. You'll need to do it manually./;w /dev/stdout' -e 'q;:a;s/\n\(.*\)/\1/p}'
but for editing files, vim is really the tool to reach for:
vim journald.conf -c 'norm /^#SystemMaxUse=$^MxA50M^[ZZ' -c '!echo "This file has been edited. You’ll need to do it manually."' -c q
which will make the change if it finds a line with #SystemMaxUse=
on its own, or it will say
This file has been edited. You’ll need to do it manually.
Press ENTER or type command to continue
and exit when they type any key. note that ^M and ^[ are enter and escape, and that U+2019 is used as the apostrophe.
Upvotes: 2
Reputation: 2068
It looks as if you were on the right track. You just need to add the else statement after the ";" following the "then" statement. Also I would split the first line from the second line with a semicolon instead of joining it with &&
.
maxline='cat journald.conf | grep "#SystemMaxUse="'; if [ $maxline == "#SystemMaxUse=" ]; then sed 's/\#SystemMaxUse=/SystemMaxUse=50M/g' journald.conf > journald.conf2 && mv journald.conf2 journald.conf; else echo "This file has been edited. You'll need to do it manually."; fi
Also in your original script, when declaring maxline you used back-ticks "`" instead of single quotes "'" which might cause problems.
Upvotes: 79
Reputation: 39
I am building a script to see whether my multiline shell script is valid since I need to verify whether a Linux directory exists in my situation.
!/bin/sh
if [ -d "/var/www/html/" ]
then
echo "html Directory exists"
else
echo "html Directory not exist"
exit 1
fi
You must adhere to this syntactic structure if you wish to create the same sort of script or condition on a single line.
if [ -d "/var/www/html/" ]; then echo "html Directory exists"; else echo "html Directory not exist "; fi
Upvotes: 2
Reputation: 51
You can use like bellow:
(( var0 = var1<98?9:21 ))
the same as
if [ "$var1" -lt 98 ]; then
var0=9
else
var0=21
fi
extends
condition?result-if-true:result-if-false
I found the interested thing on the book "Advanced Bash-Scripting Guide"
Upvotes: 4
Reputation: 9378
To summarize the other answers, for general use:
if [ foo ]; then
a; b
elif [ bar ]; then
c; d
else
e; f
fi
if [ foo ]; then a && b; elif [ bar ]; c && d; else e && f; fi
( foo && a && b ) || ( bar && c && d ) || e && f;
Remember that the AND and OR operators evaluate whether or not the result code of the previous operation was equal to true/success (0
). So if a custom function returns something else (or nothing at all), you may run into problems with the AND/OR shorthand. In such cases, you may want to replace something like ( a && b )
with ( [ a == 'EXPECTEDRESULT' ] && b )
, etc.
Also note that (
and [
are technically commands, so whitespace is required around them.
Instead of a group of &&
statements like then a && b; else
, you could also run statements in a subshell like then $( a; b ); else
, though this is less efficient. The same is true for doing something like result1=$( foo; a; b ); result2=$( bar; c; d ); [ "$result1" -o "$result2" ]
instead of ( foo && a && b ) || ( bar && c && d )
. Though at that point you'd be getting more into less-compact, multi-line stuff anyway.
Upvotes: 75
Reputation: 680
It's not a direct answer to the question but you could just use the OR-operator
( grep "#SystemMaxUse=" journald.conf > /dev/null && sed -i 's/\#SystemMaxUse=/SystemMaxUse=50M/g' journald.conf ) || echo "This file has been edited. You'll need to do it manually."
Upvotes: 9