155

In my script I need the directory of the file I am working with. For example, the file="stuff/backup/file.zip". I need a way to get the string "stuff/backup/" from the variable $file.

codeforester
  • 39,467
  • 16
  • 112
  • 140
Matt
  • 2,790
  • 6
  • 24
  • 34
  • duplicates: [get parent directory of a file in bash](https://stackoverflow.com/q/40700119/995714), [Get the parent directory of a given file](https://unix.stackexchange.com/q/351916/44425), [Getting the parent of a directory in Bash](https://stackoverflow.com/q/8426058/995714) – phuclv Mar 20 '21 at 01:21
  • @phuclv This question was asked on 2011-06-28, before all of those questions linked were posted (2016-11-20, 2017-03-16, and 2011-12-08, respectively). – Edwin Jul 12 '21 at 17:21
  • @Edwin time is irrelevant on SO. [The question with a better set of answers remain open](https://meta.stackoverflow.com/q/251938/995714) – phuclv Jul 13 '21 at 01:33

5 Answers5

249
dirname $file

is what you are looking for

Matthieu
  • 16,103
  • 10
  • 59
  • 86
58
dirname $file

will output

stuff/backup

which is the opposite of basename:

basename $file

would output

file.zip
the Tin Man
  • 158,662
  • 42
  • 215
  • 303
matchew
  • 19,195
  • 5
  • 44
  • 48
  • I figured Matt would be able to figure it from there (man dirname) :) – Matthieu Jun 28 '11 at 16:22
  • 1
    I think we are all Matt's here. Just a guess. But I was just trying to distinguish my answer from yours. =) – matchew Jun 28 '11 at 17:29
  • Yeah, I do use basename a lot too, it's very nifty =) But I could just not find anything about returning the file's dir on google! I guess I wasn't looking up the right words. Hah, all 3 of us Matt's? :D – Matt Jun 28 '11 at 19:28
  • 1
    Consider adding the necessary quotes to ensure that these commands work with names containing spaces (glob characters, etc). – Charles Duffy Sep 21 '18 at 16:39
7

Using ${file%/*} like suggested by Urvin/LuFFy is technically better since you won't rely on an external command. To get the basename in the same way you could do ${file##*/}. It's unnecessary to use an external command unless you need to.

file="/stuff/backup/file.zip"
filename=${1##*/}     # file.zip
directory=${1%/*}     # /stuff/backup

It would also be fully POSIX compliant this way. Hope it helps! :-)

MageParts
  • 179
  • 1
  • 1
  • 1
    There is *one* case where `dirname` has an advantage over the (more efficient) built-in approach, and that's if you aren't certain that your path is fully-qualified to start with. If you have `file=file.zip`, `dirname "$file"` will return `.`, whereas `${file%/*}` will return `file.zip`. – Charles Duffy Sep 21 '18 at 16:40
  • 1
    ...of course, you can branch: `case $file in */*) dir=${file%/*};; *) dir=.;; esac` is still POSIX-y and addresses the issue. – Charles Duffy Sep 21 '18 at 16:42
2

For getting directorypath from the filepath:

file="stuff/backup/file.zip"
dirPath=${file%/*}/
echo ${dirPath}
LuFFy
  • 8,799
  • 10
  • 41
  • 59
Urvin Shah
  • 61
  • 1
  • 7
1

Simply use $ dirname /home/~username/stuff/backup/file.zip

It will return /home/~username/stuff/backup/

Nishchay Sharma
  • 1,314
  • 1
  • 9
  • 18