2

I'm reviewing an old shell script. I'm not able to understand two things in it.

rm /data/log || true

value=$(cat /datafile) if [ ${value: -1} == 0 ] then echo 'do' else echo 'dont' fi

  1. value: -1 - What is this actually doing?
  2. rm /data/log || true - What this ||true doing?
Jeff Schaller
  • 67,283
  • 35
  • 116
  • 255

3 Answers3

8

${value: -1} expands to the last character of the variable contents.

${value:-1} is different from ${value: -1}!

Referring to Shell Parameter Expansion in the manual:

  1. ${value:-1} expands to the contents of the value variable, or if the variable is unset or empty, to the string "1"

  2. ${value: -1} is a short form of the ${var:offset:length} form to extract a substring of the variable contents. An offset of -1 means "one character from the end of the string". The :length part is missing, so the substring is taken from the offset to the end of the string.

    The manual says:

    Note that a negative offset must be separated from the colon by at least one space to avoid being confused with the ‘:-’ expansion.

glenn jackman
  • 85,964
  • I stand corrected. – Ljm Dullaart Sep 25 '20 at 06:43
  • Note that ${var:-default} is a Bourne and standard sh operator (from the 70s), while ${var:offset:length} is a ksh93 operator (from the 90s, now also supported by bash, zsh, mksh and busybox sh with variations, but not standard). – Stéphane Chazelas Sep 25 '20 at 06:54
  • Hey @glenn I have a question on this, if the value is unset then how it'll take the one character from the end of the string – TheDataGuy Oct 18 '20 at 09:59
4

rm /data/log || true is only (in my humble experience) useful if the script is executed with set -e. set -e makes the shell exit when a command exits with an error state. The creator of the script was apparently not aware of the -f flag for rm.

${value: -1} is probably a typo. It should be ${value:-1}, providing the default (1, not -1; the - is part of the :- syntax) for the variable expansion if value is null or not set.

If it should really be ${value: -1}, see glenn jackman's answer for the actual meaning.

Ljm Dullaart
  • 4,643
  • so during the execution, if there is no value assigned to $value or its null then number 1 will be allocation to value, Am I right? – TheDataGuy Sep 24 '20 at 07:20
  • Only if you remove the space between the : and the -. – Ljm Dullaart Sep 24 '20 at 07:21
  • 2
    This is just to say that rm -f /data/log would still exit with an error if /data/log was a directory, triggering the termination of the script under set -e. – Kusalananda Sep 24 '20 at 07:35
  • It's not a typo. Or, depending on what this program is supposed to be doing with the contents of that file, it might not be a typo. – glenn jackman Sep 24 '20 at 16:30
  • 1
    ${value: -1} takes the last character of the variable contents. The full substring expansion syntax is ${var:start:length}, but here only the starting point is given. The space is there to disambiguate it from ${value:-1}, which would indeed be a default value expansion. – ilkkachu Sep 24 '20 at 18:01
  • @Bhuvanesh ${value:-1} evaluates the substitution using the 1 in the test. But it does not update the variable value (although there is a similar syntax that would do the update). – Paul_Pedant Sep 24 '20 at 21:49
0

From bash(1): ${parameter:-word} Use Default Values. If parameter is unset or null, the expansion of word is substituted. Otherwise, the value of parameter is substituted.

|| true makes sure the command returns true. || is a short-circuiting OR operator, if the command in front returns false, the command after it is executed and the return value used.

  • Thanks I think its too techical :) correct me if my understanding is wrong. So if there is no value assigned or null for $parameter then -1 will be assigned to that parameter. Regarding ||true still not clear, what happen the command fails? for eg: instead of rm I use rmmm – TheDataGuy Sep 24 '20 at 07:06