Joshua Strot
Joshua Strot

Reputation: 2521

One line if/else condition in linux shell scripting

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

Answers (8)

Ivan
Ivan

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

Abdelrhman.Altawdy
Abdelrhman.Altawdy

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

TooManyTabs
TooManyTabs

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

Bryan
Bryan

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

Mori Kuldip
Mori Kuldip

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

Hạnh Lê Văn
Hạnh Lê Văn

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

Beejor
Beejor

Reputation: 9378

To summarize the other answers, for general use:

Multi-line if...then statement

if [ foo ]; then
    a; b
elif [ bar ]; then
    c; d
else
    e; f
fi

Single-line version

if [ foo ]; then a && b; elif [ bar ]; c && d; else e && f; fi

Using the OR operator

( foo && a && b ) || ( bar && c && d ) || e && f;

Notes

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

erlc
erlc

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

Related Questions