19

I'm working on an uninstaller script to delete the parent folder where the script is installed.

/usr/local/Myapplication/Uninstaller/uninstall.sh

So uninstall.sh has to do this:

rm- rf /usr/local/Myapplication

I can retrieve the folder where uninstall resides

SYMLINKS=$(readlink -f "$0")
UNINSTALL_PATH=$(dirname "$SYMLINKS")

But I'm still unsure of the pretty way to get the parent path. I thought of using sed to demove the "Uninstaller" part of this path, but is there an elegant way to get the path to Myapplication folder to delete it?

Thank you

2
  • in your script: cd "$(dirname "$0")" && cd .. && cd .. && [ -d Myapplication/Uninstaller ] && rm -rf Myapplication (I added a check that the directory we are about to delete contains a subdir "Uninstaller", but you could maybe add a better check, for example of a necessary file within Myapplication ?). If you don't know Myapplication, then : cd "$(dirname $0)" && cd .. && zepath="$(pwd)" && cd .. && [ -f "${zepath}/somefilesthathouldbehere" ] && rm -rf "${zepath}" Commented Nov 25, 2013 at 17:24
  • 1
    See the famous Can a Bash script tell what directory it's stored in? question, then cd .. from there. Commented Aug 15, 2015 at 11:38

8 Answers 8

30

How about using dirname twice?

APP_ROOT="$(dirname "$(dirname "$(readlink -fm "$0")")")"

The quoting desaster is only necessary to guard against whitespace in paths. Otherwise it would be more pleasing to the eye:

APP_ROOT=$(dirname $(dirname $(readlink -fm $0)))
Sign up to request clarification or add additional context in comments.

3 Comments

This works but I'm kinda iffy on using dirname twice to acheive what I want. More for learning purpose is there a way to get it in a single command line? sure APP_ROOT=$(dirname "``$(readlink -f "$0")``") would work but is there any other way?
You don't need to be iffy about that. dirname is tailored to give you the part of the directory of a path. It is exactly the right tool to do so. I update the answer for the syntax.
Note, this method is insecure for "ugly" names. A name like "-rm -rf" will break the desired behavior. Probably "." will, too. I don't know if that's the best way, but I've created a separate "correctness-focused" question here: stackoverflow.com/questions/40700119/…
8

Just get the parent of the parent directory:

my_app_path=$(dirname $(dirname $(readlink -f "$0")))

Comments

5

I put this answer as comment at 2018. But since I got a great feedback about the effectiveness of the solution, I will share it here as well :

# dir of script 
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )";
# parent dir of that dir
PARENT_DIRECTORY="${DIR%/*}"

1 Comment

Not a fan of changing the directory just to get some information that readlink could provide.
4

If you need an absolute path, then you need cd. Otherwise you can just use $(dirname $0)/..

cd $(dirname $0)/..
path=$(pwd)
cd - # go back

Comments

2

the ultimate simple way of getting the parent directory path:

PARENT_DIRECTORY="${PWD%/*}" 

4 Comments

This is the parent directory of the current directory, not where the script resides. To use this I'd have to CD to the script directory first so it's not in a way too elegant.
@MangO_O : So you need to replace PWD by script's dir : DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"; PARENT_DIRECTORY="${DIR%/*}"
@AbdennourTOUMI your solution worked well for me, seems easier than the accepted answer
Welcome @subelsky. I've added it as answer to make it more visible for others: stackoverflow.com/a/60559856/747579
2

Full path to parent dir of script, i.e. "/usr/local/bin/bla": export PARENT_OF_THIS_SCRIPT=$( cd $(dirname $0) ; pwd -P )

Just the most recent parent of script, i.e. "bla": export PARENT_DIR_OF_SCRIPT=$( cd $(dirname $0) ; pwd -P | xargs basename )

Comments

1

Why don't you simply add ../ at the end of the path?

2 Comments

This wouldn't work with rm, UNINSTALL_PATH=$(dirname "$SYMLINKS")/../ is not the correct father path when used with the rm command
Also you'd need to add /../. And if, for whatever reason, $UNINSTALL_PATH is empty, /../ == / and you're wiping the hard drive.
1

As $0 can have suprising behavior, here is a solution using BASH_SOURCE[0]:

#/bin/bash

PARENT_DIR=$(dirname $(dirname $(readlink -f "${BASH_SOURCE[0]}")))

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.