20

Am trying to write a one-liner that can probe the output of df -h and alert when one of the partitions is out [or almost] of space. It's the part using xargs that kicking me in the ass now...

echo 95 | xargs -n1 -I{} [ {} -ge 95 ] && echo "No Space on disk {}% full -- remove old backups please"

How can i make the second {} show "95" too?

Gilles 'SO- stop being evil'
  • 807,993
  • 194
  • 1,674
  • 2,175
JWL
  • 377
  • 1
  • 2
  • 10

3 Answers3

28

That && is not part of the xargs command, it's a completely separate invocation. I think you'll want to execute a shell explicitly:

echo 95 | xargs -I_percent sh -c '[ "$1" -ge 95 ] && echo "No Space on disk $1% full -- remove old backups please"' sh _percent

Note also that I'm using _percent instead of {} to avoid extra quoting headaches with the shell. It's not a shell variable; still just an xargs replacement string.

Kusalananda
  • 320,670
  • 36
  • 633
  • 936
ckhan
  • 4,132
  • 22
  • 21
4

An alternative way, which is more readable, is to define a separate function which contains all your other commands and then call that function with xargs in a sub-shell.

Hence, for example:

myfunc(){
  [ "$1" -ge 95 ] && echo "No Space on disk $1% full -- remove old backups please"
  echo "Another command echoing $1"
}

export -f myfunc

echo 95 | xargs -n1 -I_percent -- sh -c 'myfunc "_percent"'
shivams
  • 4,505
  • 3
  • 19
  • 36
0

You can just use the sh option mentioned and enclose the command in single quotes as show below with an extra equivalent if version:

#Your example
echo 95 | xargs -n1 -I{} sh -c '[ {} -ge 95 ] && echo "No Space on disk {}% full -- remove old backups please"'

#if equivalent
echo 95 | xargs -n1 -I{} sh -c 'if [ {} -ge 95 ]; then echo "No Space on disk {}% full -- remove old backups please"; fi'

Using xargs with alias in -I option for better readability

echo 95 | xargs -n1 -IusedSpace sh -c 'if [ usedSpace -ge 95 ]; then echo "No Space on disk usedSpace% full -- remove old backups please"; fi'

With if and chain as many command as You wish separated by semicolon ; below example with 2 and 4 commands chained

# 2 independent commands
echo 95 | xargs -n1 -I{} sh -c 'if [ {} -ge 95 ]; then echo "No Space on disk {}% full -- remove old backups please"; echo "Value processed {}"; fi'
# 4 independent commands
echo 95 | xargs -n1 -I{} sh -c 'if [ {} -ge 95 ]; then echo "No Space on disk {}% full -- remove old backups please"; echo "Space left on disk $( expr 100 - {})%"; echo "Space used {}%"; echo "Value processed {}"; fi'

I added the else case in your example, It prints the left disk space

#If with else block
echo 80 | xargs -n1 -I{} sh -c 'if [ {} -ge 95 ]; then echo "No Space on disk {}% full -- remove old backups please"; else echo "Space left on disk $( expr 100 - {})%"; fi'

#Equivalent
echo 80 | xargs -n1 -I{} sh -c '[ {} -ge 95 ] && echo "No Space on disk {}% full -- remove old backups please"; [ {} -ge 95 ] || echo "Space left on disk $( expr 100 - {})%"'

Another modification could be isolate the 95 percent of limit usage in a variable as show below:

echo 96 | xargs -n1 -IusedSpace sh -c 'usageLimit=95; if [ usedSpace -ge ${usageLimit} ]; then echo "No Space on disk usedSpace% full -- remove old backups please"; else echo "Space left on disk $( expr 100 - usedSpace)%"; fi'

Happy scripting!!! @enrique