0

I am very much new in shell scripting and just got the below mentioned export of variable in shell :

export VAR_FILE=${*: -1}

Can anyone help me to understand this ,as I am not able to understand this

1
  • 1
    A simpler way to get (specifically) the last argument is ${!#}. Commented Sep 5, 2018 at 12:54

2 Answers 2

4

Ok, let's grab bash manual and go:

export variable[=value] - "Mark each name to be passed to child processes in the environment.". That means that if you run another process from this shell (ie. a subshell with a command: sh -c 'echo $variable') it will share the variable value.

$* - "($*) Expands to the positional parameters, starting from one.". For example: sh -c 'echo $1' -- 1, $1 will expand to the "first position argument". So $* expands to all positional parameters.

${parameter:offset:length} - This is named "substring expansion". It expands to characters starting at offset. If the paramter is * or @ it exapnds to positional parameter, ie: ${*:2:1} is equal to $2. You can also give negative offset, it then counts from the back. If you omit :length part, it assumes that length is infinite (to the end of string, to the last positional parameter).

${*:-1} - this will not work as you expect, cause ${parameter:-word} expands to 1 if $* is null or unset. That means that we need a space between :- so bash does not confuse substring expansion with :-.

${*: -1} - this will give you the last positional parameter. ie. sh -c 'echo ${*: -1}' -- 1 2 3 will output 3.

export VAR_FILE=${*: -1} - get's the last positional parameter, assigns it to VAR_FILE variable and set's that VAR_FILE variable will be exported to subprocesses.

Sign up to request clarification or add additional context in comments.

Comments

2

$* is a special variable which expands to the list of positional parameters (arguments to your script), separated by a space character.

${list: -1} expands to the last element of a list.

So this sets the environment variable VAR_FILE to the last argument passed to the script.


Note that for an array that you define yourself, the syntax would be different:

list=( a b 'c d' )
export foo=${list[*]: -1} # list[*] instead of just *

2 Comments

Actually, this is one of the few places where the * version works as well as @ -- they're in contexts where word splitting and glob expansion don't occur, and there's only one argument (/element) being extracted means that *'s usual problem of mushing multiple arguments together doesn't apply.
@Gordon thanks - I decided to remove that part of my answer as it didn't really relate directly to the question and made things potentially more confusing.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.