Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

"${0%/*}" and "${0##*/}" in sh [duplicate]

Tags:

bash

sh

These are excerpts from a brew command.

BREW_FILE_DIRECTORY=$(chdir "${0%/*}" && pwd -P)
export HOMEBREW_BREW_FILE="$BREW_FILE_DIRECTORY/${0##*/}"

What do ${0%/*} and ${0##*/} mean in shell?

like image 460
prosseek Avatar asked Jun 22 '15 12:06

prosseek


2 Answers

These are shell parameter expansions:

  • ${var%/*} - remove everything after the last occurrence of /.
  • ${var##*/} - remove everything up to the last occurrence of /.

Since you are in a script, $0 refers to the name of the script itself.

All together, this is returning either the path or the name of the script that you are running. So your are kind of doing:

BREW_FILE_DIRECTORY=$(chdir <path_of_script> && pwd -P)
export HOMEBREW_BREW_FILE="$BREW_FILE_DIRECTORY/<script_name>"

Test

$ r="hello/how/are/you"
$ echo ${r%/*}
hello/how/are
$ echo ${r##*/}
you

From the above-mentioned link (edited versions to make them shorter):

${parameter##word}

The word is expanded to produce a pattern just as in filename expansion. If the pattern matches the beginning of the expanded value of parameter, then the result of the expansion is the expanded value of parameter with the longest matching pattern (the ‘##’ case) deleted. If parameter is ‘@’ or ‘*’, the pattern removal operation is applied to each positional parameter in turn, and the expansion is the resultant list.

${parameter%word}

The word is expanded to produce a pattern just as in filename expansion. If the pattern matches a trailing portion of the expanded value of parameter, then the result of the expansion is the value of parameter with the shortest matching pattern (the ‘%’ case) deleted. If parameter is ‘@’ or ‘*’, the pattern removal operation is applied to each positional parameter in turn, and the expansion is the resultant list.

And regarding $0 itself, see Bash reference manual -> 6.1 Invoking bash:

If arguments remain after option processing, and neither the -c nor the -s option has been supplied, the first argument is assumed to be the name of a file containing shell commands (see Shell Scripts). When Bash is invoked in this fashion, $0 is set to the name of the file, and the positional parameters are set to the remaining arguments. Bash reads and executes commands from this file, then exits.

like image 143
fedorqui 'SO stop harming' Avatar answered Sep 17 '22 23:09

fedorqui 'SO stop harming'


These are string manipulation operations. You can refer to this document

${string%substring}  # Deletes shortest match of $substring from back of $string.
${string##substring} # Deletes longest match of $substring from front of $string.

Having this, we can explain what the operators are doing in your code.

${0%/*}

Assuming $0 is a file name, it will give you the directory it is located in. It works the same way as the dirname command.

${0##*/}

Assuming $0 is a file name, it will give you the file name without the leading path. It works the same way as the basename command.

like image 26
hek2mgl Avatar answered Sep 18 '22 23:09

hek2mgl