How to extract directory path from file path?
BashBash Problem Overview
In Bash, if VAR="/home/me/mydir/file.c"
, how do I get "/home/me/mydir"
?
Bash Solutions
Solution 1 - Bash
dirname
and basename
are the tools you're looking for for extracting path components:
$ VAR='/home/pax/file.c'
$ DIR="$(dirname "${VAR}")" ; FILE="$(basename "${VAR}")"
$ echo "[${DIR}] [${FILE}]"
[/home/pax] [file.c]
They're not internal bash
commands but they are part of the POSIX standard - see dirname
and basename
. Hence, they're probably available on, or can be obtained for, most platforms that are capable of running bash
.
Solution 2 - Bash
$ export VAR=/home/me/mydir/file.c
$ export DIR=${VAR%/*}
$ echo "${DIR}"
/home/me/mydir
$ echo "${VAR##*/}"
file.c
To avoid dependency with basename
and dirname
Solution 3 - Bash
On a related note, if you only have the filename or relative path, dirname
on its own won't help. For me, the answer ended up being readlink
.
fname='txtfile'
echo $(dirname "$fname") # output: .
echo $(readlink -f "$fname") # output: /home/me/work/txtfile
You can then combine the two to get just the directory.
echo $(dirname $(readlink -f "$fname")) # output: /home/me/work
Solution 4 - Bash
If you care target files to be symbolic link, firstly you can check it and get the original file. The if clause below may help you.
if [ -h $file ]
then
base=$(dirname $(readlink $file))
else
base=$(dirname $file)
fi
Solution 5 - Bash
HERE=$(cd $(dirname $BASH_SOURCE) && pwd)
where you get the full path with new_path=$(dirname ${BASH_SOURCE[0]})
. You change current directory with cd
new_path and then run pwd
to get the full path to the current directory.
Solution 6 - Bash
I was playing with this and came up with an alternative.
$ VAR=/home/me/mydir/file.c
$ DIR=`echo $VAR |xargs dirname`
$ echo $DIR
/home/me/mydir
The part I liked is it was easy to extend backup the tree:
$ DIR=`echo $VAR |xargs dirname |xargs dirname |xargs dirname`
$ echo $DIR
/home
Solution 7 - Bash
You could try something like this using approach for How to find the last field using 'cut':
Explanation
rev
reverses/home/user/mydir/file_name.c
to bec.eman_elif/ridym/resu/emoh/
cut
uses/
as the delimiter, and chooses the second field, which isridym/resu/emoh/
, which deletes string up to the first occurrence of/
- lastly, we reverse it again to get
/home/user/mydir
$ VAR="/home/user/mydir/file_name.c"
$ echo $VAR | rev | cut -d"/" -f2- | rev
/home/user/mydir
Solution 8 - Bash
Here is a script I used for recursive trimming. Replace $1 with the directory you want, of course.
BASEDIR=$1
IFS=$'\n'
cd "$BASEDIR"
for f in $(find . -type f -name ' *')
do
DIR=$(dirname "$f")
DIR=${DIR:1}
cd "$BASEDIR$DIR"
rename 's/^ *//' *
done