Get the parent directory of a given file

34,568

Solution 1

Assuming

$ file=./Tools/build.bat

With a POSIX compatible shell (including zsh):

$ echo "${file%/*}"
./Tools

With dirname:

$ echo "$(dirname -- "$file")"
./Tools

(at least GNU dirname takes options, so the -- is required in case the path starts with a dash.)

Solution 2

If you are using zsh try :h modifier

cd $file:h

You can add n of them to go n levels up in directory structure.

Solution 3

this is quite simple with the command dirname, just do the folowing:

cd "$(dirname -- "$file")"

now you can even go further on this

file=/home/switch87/.bashrc
cd "$(dirname -- "$file")"
cd "$(dirname -- "$file")"/..

first cd will get you to /home/switch87, the seccond to /home

Solution 4

get the directory of the file in a very general way (when file is known with a relative or absolute pathname, or no path at all):

the_dir="$(cd -P "$(dirname "${filename}")";pwd)"

So to get the parent of that directory:

the_parent_dir="$(cd -P "$(dirname "${filename}")/..";pwd)"

cd -P : print the "real" (physical) path, instead of a path using symbolic links. If you take the -P out it also works, but you may get a different result ( for exemple: cd / ; ln -s /long/path/here shortcut ; cd shortcut ; pwd will show you the path: /shortcut, whereas if you added -P to cd you would see /long/path/here instead)

Solution 5

I prefer to use a combination of readlink and dirname.

parent=$(readlink -f "$(dirname "$file")")
cd $parent

dirname cuts the filename from the path and readlink -f turns $path/.. into a canonical path.

Share:
34,568

Related videos on Youtube

Tim
Author by

Tim

Elitists are oppressive, anti-intellectual, ultra-conservative, and cancerous to the society, environment, and humanity. Please help make Stack Exchange a better place. Expose elite supremacy, elitist brutality, and moderation injustice to https://stackoverflow.com/contact (complicit community managers), in comments, to meta, outside Stack Exchange, and by legal actions. Push back and don't let them normalize their behaviors. Changes always happen from the bottom up. Thank you very much! Just a curious self learner. Almost always upvote replies. Thanks for enlightenment! Meanwhile, Corruption and abuses have been rampantly coming from elitists. Supportive comments have been removed and attacks are kept to control the direction of discourse. Outright vicious comments have been removed only to conceal atrocities. Systematic discrimination has been made into policies. Countless users have been harassed, persecuted, and suffocated. Q&A sites are for everyone to learn and grow, not for elitists to indulge abusive oppression, and cover up for each other. https://softwareengineering.stackexchange.com/posts/419086/revisions https://math.meta.stackexchange.com/q/32539/ (https://i.stack.imgur.com/4knYh.png) and https://math.meta.stackexchange.com/q/32548/ (https://i.stack.imgur.com/9gaZ2.png) https://meta.stackexchange.com/posts/353417/timeline (The moderators defended continuous harassment comments showing no reading and understanding of my post) https://cs.stackexchange.com/posts/125651/timeline (a PLT academic had trouble with the books I am reading and disparaged my self learning posts, and a moderator with long abusive history added more insults.) https://stackoverflow.com/posts/61679659/revisions (homework libels) Much more that have happened.

Updated on September 18, 2022

Comments

  • Tim
    Tim over 1 year

    Suppose file stores the pathname of a non-dir file.

    How can I get its parent directory?

    why does the following way by appending /.. to its value not work

    $ cd $file/..   
    cd: ./Tools/build.bat/..: No such file or directory
    

    Thanks.

    • schaiba
      schaiba about 7 years
      Example of such a pathname?
    • ivanivan
      ivanivan about 7 years
      dirname may be what you want
    • Tim
      Tim about 7 years
      @schaiba ./Tools/build.bat as in the example
    • Sahil Chaudhary
      Sahil Chaudhary about 7 years
      Do you ever search before asking or ask basic questions just for the upvotes? It's hard to believe you couldn't find this doing a little searching.
  • Stéphane Chazelas
    Stéphane Chazelas about 7 years
    Also works in csh/tcsh where it comes from though in those shells, you'll need to add a :q to account for directory names that contain blanks or wildcards.
  • Tim
    Tim about 7 years
    Thanks. why does the following way by appending /.. to its value not work
  • Tim
    Tim about 7 years
    okay, I see it is because $file isn't a directory
  • gardenhead
    gardenhead about 7 years
    Do you really need the echo?
  • Pysis
    Pysis about 7 years
    Just a note: I use dirname all the time, as I find it more expressive.
  • ilkkachu
    ilkkachu about 7 years
    @gardenhead, only for demonstration. Of course really we'd just do somecommand "${file%/*}" (And even for printing, printf would arguably be better.)
  • Gilles 'SO- stop being evil'
    Gilles 'SO- stop being evil' about 7 years
    That potentially gives a different path to the directory, which may not be desirable.