14

I tried to to run echo ${@:$#} and it echoes my current shell.

I found out that echo ${#} echoes 0.

I didn't find any resources about the results.

I am trying to understand that part so I can understand a docker script that I want to use. The script is:

alias enhance='function ne() { docker run --rm -v "$(pwd)/`dirname ${@:$#}`":/ne/input -it alexjc/neural-enhance ${@:1:$#-1} "input/`basename ${@:$#}`"; }; ne'
Jeff Schaller
  • 67,283
  • 35
  • 116
  • 255
  • 5
    There is no need to encapsulate a function in an alias. It just adds an unnecessary layer. –  Mar 06 '21 at 10:19
  • 1
    (and as another aside, it's more portable not to use the (POSIX-noncompliant, borrowed from legacy ksh for compatibility with pre-POSIX ksh releases but not actually fully compatible with ksh's behavior) function keyword at all -- see both entries in the first and last tables in https://wiki.bash-hackers.org/scripting/obsolete; thus, it's better just ne() { docker run ...; }, and that'll define a ne you can run as-is; no alias, no function). – Charles Duffy Mar 06 '21 at 15:16

1 Answers1

25

In every POSIX compliant shell,

  • $# is the number of arguments to the function or script, the number of positional parameters.
  • $@ is the list of arguments to the function or script, the list $1, $2, etc. of positional parameters.

In Bash, Ksh and Zsh, etc.:

  • ${@:offset:n} are the n arguments starting at parameter offset, or all arguments to the end from offset if n is missing.

Thus ${@:$#} is the last argument given to the function at hand, whereas ${@:1:$#-1} is the remaining arguments. The last argument could also be written ${@: -1} (in Bash release 4.3 or later).

Quasímodo
  • 18,865
  • 4
  • 36
  • 73
  • 3
    Note that while Bourne's "$@" is "$1" "$2"..., Korn's "${@:offset:length}" also includes $0 which is not a positional parameter, but the name of the script/function (possibly sourced file). So if $# is 0, ${@:$#} will be that $0. For the last argument, see zsh/yash's ${@[-1]} instead (predates the Korn syntax) or even older csh/zsh's $argv[$#], or the POSIX: eval "last=\${$#}" – Stéphane Chazelas Mar 06 '21 at 15:05