Skip to main content
added 312 characters in body
Source Link
ilkkachu
  • 148.1k
  • 16
  • 268
  • 441

No, "${@:-1}" doesn't. But "${@: -1}" does.

But note that at least in Bash and Ksh, if there are no positional parameters, then "${@: -1}" gives "$0", i.e. the shell name. This is similar to how using ${@:0} gives $0 and all positional the positional parameters. Zsh doesn't seem to give $0 with ${@: -1} or the cleaner ${@[-1]}.

The gotcha here is that ${var:-value} is a standard expansion which expands to the default value value if var is unset or empty. The substring/array slice expansion ${var:p:n}, of which ${@: -1} is a special case, is not standard and the shell interprets ${@:-1} as the default value expansion on $@. The space removes the ambiguity, and so would putting the index in a variable, e.g. i=-1; echo "${@:i}"

set -- a b c echo "${@: -1}" # prints 'c', the last element echo "${@:-1}" # prints 'a b c' set -- echo "${@: -1}" # prints '/bin/bash' or something like that echo "${@:-1}" # prints '1', the default value given echo "${@:-no args}" # prints 'no args' 

Also as noted in comments, the expansion in : ${fdir:="${@:-1}"} is unquoted, so it may cause the shell to generate an arbitrarily long list of filenames. That could be prevented with : "${fdir:="${@: -1}"}", or the perhaps more readable [ -z "$fdir"] && fdir="${@: -1}"

No, "${@:-1}" doesn't. But "${@: -1}" does.

But note that at least in Bash and Ksh, if there are no positional parameters, then "${@: -1}" gives "$0", i.e. the shell name. This is similar to how using ${@:0} gives $0 and all positional the positional parameters. Zsh doesn't seem to give $0 with ${@: -1}.

The gotcha here is that ${var:-value} is a standard expansion which expands to the default value value if var is unset or empty. The substring/array slice expansion ${var:p:n}, of which ${@: -1} is a special case, is not standard and the shell interprets ${@:-1} as the default value expansion on $@. The space removes the ambiguity, and so would putting the index in a variable, e.g. i=-1; echo "${@:i}"

set -- a b c echo "${@: -1}" # prints 'c', the last element echo "${@:-1}" # prints 'a b c' set -- echo "${@: -1}" # prints '/bin/bash' or something like that echo "${@:-1}" # prints '1', the default value given echo "${@:-no args}" # prints 'no args' 

No, "${@:-1}" doesn't. But "${@: -1}" does.

But note that at least in Bash and Ksh, if there are no positional parameters, then "${@: -1}" gives "$0", i.e. the shell name. This is similar to how using ${@:0} gives $0 and all positional the positional parameters. Zsh doesn't seem to give $0 with ${@: -1} or the cleaner ${@[-1]}.

The gotcha here is that ${var:-value} is a standard expansion which expands to the default value value if var is unset or empty. The substring/array slice expansion ${var:p:n}, of which ${@: -1} is a special case, is not standard and the shell interprets ${@:-1} as the default value expansion on $@. The space removes the ambiguity, and so would putting the index in a variable, e.g. i=-1; echo "${@:i}"

set -- a b c echo "${@: -1}" # prints 'c', the last element echo "${@:-1}" # prints 'a b c' set -- echo "${@: -1}" # prints '/bin/bash' or something like that echo "${@:-1}" # prints '1', the default value given echo "${@:-no args}" # prints 'no args' 

Also as noted in comments, the expansion in : ${fdir:="${@:-1}"} is unquoted, so it may cause the shell to generate an arbitrarily long list of filenames. That could be prevented with : "${fdir:="${@: -1}"}", or the perhaps more readable [ -z "$fdir"] && fdir="${@: -1}"

Source Link
ilkkachu
  • 148.1k
  • 16
  • 268
  • 441

No, "${@:-1}" doesn't. But "${@: -1}" does.

But note that at least in Bash and Ksh, if there are no positional parameters, then "${@: -1}" gives "$0", i.e. the shell name. This is similar to how using ${@:0} gives $0 and all positional the positional parameters. Zsh doesn't seem to give $0 with ${@: -1}.

The gotcha here is that ${var:-value} is a standard expansion which expands to the default value value if var is unset or empty. The substring/array slice expansion ${var:p:n}, of which ${@: -1} is a special case, is not standard and the shell interprets ${@:-1} as the default value expansion on $@. The space removes the ambiguity, and so would putting the index in a variable, e.g. i=-1; echo "${@:i}"

set -- a b c echo "${@: -1}" # prints 'c', the last element echo "${@:-1}" # prints 'a b c' set -- echo "${@: -1}" # prints '/bin/bash' or something like that echo "${@:-1}" # prints '1', the default value given echo "${@:-no args}" # prints 'no args'