Bash script get one directory back - bash

I can get my current working directory with
my_dir=$(pwd)
echo $my_dir
/files/work/test
How do I get /files/work I don't want to change directories. I just need to get the /files/work directory.

Try one of these (assuming you didn't manually change $PWD):
echo "${PWD%/*}"
dirname "$PWD"
(cd .. && pwd)

echo `dirname \`pwd\``
It ll result the parent directory of present working directory

You can ascend one directory above:
$ cd ..
or you can dirname to print the one directory above:
$ dirname "/files/work/test"
/files/work

Related

Writing a loop for removing files from subdirectories

Im trying to figure out how to write a loop to remove specific files from multiple subdirectories which are all very similar in structure.
Within /main_directory/ there are 50 sub directories all with different names.
So /main_directory/sub1 /main_directory/testsub1 /main_directory/sub1_practice and so on. Each subdirectory has different file types and I want to remove a specific type, call it .txt.
I want to write a loop something like this:
for file in ./main_directory/*; cd $file; rm *.txt; done
So that within each subdirectory in main_directory, all .txt files are removed.
Apologies for the basic question, but I can only find solutions for subdirectories that have the same name or prefix, not all differently named subdirectories.
I tried for file in ./main_directory/*; cd $file; rm *.txt; done
and received the error that there is no such file or directory for all the subdirectories
If you cd into the directory, you have to remember to return to your original working directory afterward otherwise every future command will be executed relative to whatever directory you last successfully changed to.
Some examples that should work:
# don't change directories at all
for dir in ./main_directory/* ; do
rm "$dir"/*.txt
done
# explicitly change back to the original directory
for dir in ./main_directory/* ; do
cd "$dir" && { rm *.txt ; cd - ; }
done
# change directories in a subshell, so that your
# original working directory is restored afterward
for dir in ./main_directory/* ; do
(
cd "$dir" && rm *.txt
)
done
# without a loop, using the find command
find ./main_directory -type f -name '*.txt' -delete
After descending in the first directory, you don't return to the original location. The second directory will be searched for in the first one. An improvement of your code will be adding cd ..
for directory in ./main_directory/*; do
cd "$directory" || continue
rm *.txt
cd ..
done
This code is wrong without the || continue part.
When the cd "$directory" fails, it will start removing files from the wrong location and next put you in the parent directory. You can change it into cd "$directory" || continue.
An alternative is starting it in a subprocess:
for directory in ./main_directory/*; do
(
cd "$directory" || continue
rm *.txt
)
done
You still need the || continue, because you don't want to remove files from the wrong directory.
In this example, you don't need a loop. You can use
rm main_directory/*.txt

get folder name with find ... -name command in bash

Trying to get name of venv folder for activating it in bash script located inside the project. Because someone could use for venv another name like 'someones_env'
projectdir=$(cd ../../ && pwd)
echo "$(dirname "$projectdir")"
venvdir=$(find "$(dirname "$projectdir")" -name '*env')
echo "$(dirname "$venvdir")"
source "$(dirname "$venvdir")"/bin/activate
but $venvdir becomes the same as $projectdir instead of 'someones_env'
what am i doing wrong?
thanks
The directory of the *env folder is the project directory, that's why dirname "$venvdir" becomes the same as the project directory. Without dirname it should work.
Also, the directory of ../../ is ../../../, this might also be giving you some issues. If you are already in a directory, there's no need to use dirname. dirname calculates the parent directory.

Script directory path regardless of current/working directory

Is there a way to get the script directory regardless of change in current directory that occurred during script execution.
echo $(dirname "$(readlink -f "$0")")
cd /tmp
echo $(dirname "$(readlink -f "$0")")
/home/user/test
/tmp
In the example above, I need /home/user/test both times, without storing it to a variable.
This should do the job in your script:
dir="$(readlink /proc/$PPID/cwd)"

Cd into subdirectories using Bash

I am writing a shell script to cd into subdirectories in a main directory, however I am getting an error that directory does not exists, so when I print out the value of the directory value I see that directory names are listed in a weird way,can someone help me to correct this error.
Code:
for d in ./*
do
(cd $d && ./example.c)
done
Output when I do echo $d:
./Directory, Test
./Directory, Test1
Orignal directory names in the parent directory:
Test,Directory
Test1,Directory

Retrieve parent directory of script

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
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)))
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%/*}"
Just get the parent of the parent directory:
my_app_path=$(dirname $(dirname $(readlink -f "$0")))
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
the ultimate simple way of getting the parent directory path:
PARENT_DIRECTORY="${PWD%/*}"
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 )
Why don't you simply add ../ at the end of the path?
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]}")))

Resources