How to get the last part of dirname in Bash
BashShellDirnameBash Problem Overview
Suppose I have a file /from/here/to/there.txt
, and want to get only the last part of its dirname to
instead of /from/here/to
, what should I do?
Bash Solutions
Solution 1 - Bash
You can use basename
even though it's not a file. Strip off the file name using dirname
, then use basename
to get the last element of the string:
dir="/from/here/to/there.txt"
dir="$(dirname $dir)" # Returns "/from/here/to"
dir="$(basename $dir)" # Returns just "to"
Solution 2 - Bash
The opposite of dirname
is basename
:
basename "$(dirname "/from/here/to/there.txt")"
Solution 3 - Bash
Using bash
string functions:
$ s="/from/here/to/there.txt"
$ s="${s%/*}" && echo "${s##*/}"
to
Solution 4 - Bash
Using Bash parameter expansion, you could do this:
path="/from/here/to/there.txt"
dir="${path%/*}" # sets dir to '/from/here/to' (equivalent of dirname)
last_dir="${dir##*/}" # sets last_dir to 'to' (equivalent of basename)
This is more efficient since no external commands are used.
Solution 5 - Bash
Pure BASH way:
s="/from/here/to/there.txt"
[[ "$s" =~ ([^/]+)/[^/]+$ ]] && echo "${BASH_REMATCH[1]}"
to
Solution 6 - Bash
An awk
way of doing it would be:
awk -F'/' '{print $(NF-1)}' <<< "/from/here/to/there.txt"
Explanation:
-F'/'
sets field separator as "/"- print the second last field
$(NF-1)
<<<
uses anything after it as standard input (wiki explanation)
Solution 7 - Bash
One more way
IFS=/ read -ra x <<<"/from/here/to/there.txt" && printf "%s\n" "${x[-2]}"
Solution 8 - Bash
This question is something like THIS.
For solving that you can do:
DirPath="/from/here/to/there.txt"
DirPath="$(dirname $DirPath)"
DirPath="$(basename $DirPath)"
echo "$DirPath"
As my friend said this is possible as well:
basename `dirname "/from/here/to/there.txt"`
In order to get any part of your path you could do:
echo "/from/here/to/there.txt" | awk -F/ '{ print $2 }'
OR
echo "/from/here/to/there.txt" | awk -F/ '{ print $3 }'
OR
etc
Solution 9 - Bash
The top answer is absolutely correct for the question asked. In a more generic case with the needed directory in the middle of a long path, this approach leads to a hard to read code. For example :
dir="/very/long/path/where/THIS/needs/to/be/extracted/text.txt"
dir="$(dirname $dir)"
dir="$(dirname $dir)"
dir="$(dirname $dir)"
dir="$(dirname $dir)"
dir="$(dirname $dir)"
dir="$(basename $dir)"
In this case one can use:
IFS=/; set -- "/very/long/path/where/THIS/needs/to/be/extracted/text.txt"; set $1; echo $6
THIS