Get the parent directory for a file

25

5

I want to get just the name of the parent directory for a file.

Example: When I have path=/a/b/c/d/file, I want only d and not /a/b/c/d (which I get from dirname $path) as output.

Is there any sophisticated way to do this?

shraddha

Posted 2013-01-20T06:02:33.073

Reputation: 351

Answers

27

It sounds like you want the basename of the dirname:

$ filepath=/a/b/c/d/file
$ parentname="$(basename "$(dirname "$filepath")")"
$ echo "$parentname"
d

Gordon Davisson

Posted 2013-01-20T06:02:33.073

Reputation: 28 538

why am I receiving . instead of the parent directory on debian? – Amir – 2015-11-10T10:17:10.333

@Amir: Are you starting with a full path, or just a filename? If it's just a filename, the dirname command will assume it's in the current directory (aka "."). – Gordon Davisson – 2015-11-10T15:09:37.753

well, I am using this: parentname="$(basename "$(dirname "$pwd")")" – Amir – 2015-11-10T15:33:43.223

1@Amir: Shell variables are case sensitive, and PWD must be capitalized. Try parentname="$(basename "$(dirname "$PWD")")". – Gordon Davisson – 2015-11-10T17:31:59.747

5

You can use pwd to get the current working directory, and use parameter expansion to avoid forking it into another (sub)shell.

echo ${PWD##*/}

Edit: proven source

fire

Posted 2013-01-20T06:02:33.073

Reputation: 161

The question has nothing to do with the current directory. You could use ${path##*/} – Matteo – 2013-01-20T09:22:52.907

2

I think this is a less-resource solution:

 $ filepath=/a/b/c/d/file
 $ echo ${${filepath%/*}##*/}
 d

edit: Sorry, nested expansion isn't possible in bash, but it works in zsh. Bash-version:

 $ filepath=/a/b/c/d/file
 $ path=${filepath%/*}
 $ echo ${path##*/}
 d

uzsolt

Posted 2013-01-20T06:02:33.073

Reputation: 1 017

There are some edge cases this doesn't handle well, mainly when there isn't a full multilevel path. For example, try it with filepath=file or filepath=/file`. – Gordon Davisson – 2013-01-20T22:31:57.193

Indeed. But what is the parent directory of foofile? If it isn't full path can't know (maybe if foofile is an existing file not only a "string"). – uzsolt – 2013-01-21T08:54:09.653

1

In bash, in one line:

$ dirname /a/b/c/d/file | sed 's,^\(.*/\)\?\([^/]*\),\2,'

julian67

Posted 2013-01-20T06:02:33.073

Reputation: 11

2can you please elaborate the procedures involved? it can be of help to future readers. also, please try not to write 1/2 line answers. – Lorenzo Von Matterhorn – 2013-04-28T19:18:56.800

0

I like Julian67's answer above best, but here is a bit an expanded version:

file_path = "a/b/c/d/file.txt"
parent=$(echo $file_path | sed -e 's;\/[^/]*$;;') # cut away "/file.txt";'$' is end of string
parent=$(echo $parent | sed -e 's;.*\/;;')  # cut away "/a/b/c/"
echo $parent # --> you get "d"

Dominic van der Zypen

Posted 2013-01-20T06:02:33.073

Reputation: 101