TJ L
TJ L

Reputation: 24472

Get last dirname/filename in a file path argument in Bash

I'm trying to write a post-commit hook for SVN, which is hosted on our development server. My goal is to try to automatically checkout a copy of the committed project to the directory where it is hosted on the server. However I need to be able to read only the last directory in the directory string passed to the script in order to checkout to the same sub-directory where our projects are hosted.

For example if I make an SVN commit to the project "example", my script gets "/usr/local/svn/repos/example" as its first argument. I need to get just "example" off the end of the string and then concat it with another string so I can checkout to "/server/root/example" and see the changes live immediately.

Upvotes: 364

Views: 434323

Answers (7)

suahuab
suahuab

Reputation: 1

Not a 'deepthroat' programmer at all here, but, couldn't sth like this also work?:

MYPATH="/path/to/dir"

MYPATHLAST=$(echo "${MYPATH}" | sed -r "s/^(.*)([/])(.*)$/\3/")

echo "${MYPATHLAST}"

Maybe a bit extensive, this, and maybe out of context, but, often useful, sed. It literally takes any last word/part at the end of the given line '(.*)', referenced by group-id 3. (Maybe you could do it someway with e.g. egrep too, but the question there is how to handle the repetitive slashes. You only need the final term after the last slash in the line.).

My 'context' is a bash script with zenity '--file-selection --directory' of which the output goes to this rsync:

rsync -rauW --delete --inplace --no-compress --info=progress2 ${EXCL} --mkpath ${SOURCE}/ ${DESTINATION}

(Nevermind the (unquoted) EXCL var, it references possible exludes also rendered through zenity.)

The problem is that '--mkpath' does create a dir by means of a bash script without zenity but not bmo a bash script with zenity --file-selection. You would have to type the new dir at destination from zenity --file-selection, if it doesn't exist. If rsync would create the new dir (the last word of the path-line), I could just select one destination dir upwards with zenity --file-selection to create the new dir with the same name as source dir within it.

So I'm looking for a way to first create the dir with the same name at destination (mkdir -p probably) and then run rsync on it.

Upvotes: 0

ccalvert
ccalvert

Reputation: 4476

Building on Dennis Williamson's answer we can get only the directory name from a particular subdirectory:

ls -d /home/$USER/Git/React/*/  |  while read line; do
   echo "$(basename $line)"
done

Suppose JsObjects has 7 subdirecties:

$ ls -d /home/$USER/Git/JsObjects/*/
/home/ubuntu/Git/JsObjects/Cordova/            /home/ubuntu/Git/JsObjects/JavaScript/
/home/ubuntu/Git/JsObjects/Data/               /home/ubuntu/Git/JsObjects/Python/
/home/ubuntu/Git/JsObjects/HtmlCssJavascript/  /home/ubuntu/Git/JsObjects/Utilities/
/home/ubuntu/Git/JsObjects/JQueryMobile/

We can get the directory names like this:

$ ls -d /home/$USER/Git/JsObjects/*/  |  while read line; do
   echo "$(basename $line)"
done
Cordova
Data
HtmlCssJavascript
JQueryMobile
JavaScript
Python
Utilities

Upvotes: 0

xerostomus
xerostomus

Reputation: 557

If the file is in the current directory, you will invite this short:

cd /dev/shm
basename $(pwd) # shm

I already have had this sed command, although I admit it is not much practical:

path="/dev/shm"
sed -r "s/^.*\/(.*)$/\1/" <<< $path # shm

Upvotes: -1

sth
sth

Reputation: 229854

basename does remove the directory prefix of a path:

$ basename /usr/local/svn/repos/example
example
$ echo "/server/root/$(basename /usr/local/svn/repos/example)"
/server/root/example

Upvotes: 529

Dennis Williamson
Dennis Williamson

Reputation: 360665

Bash can get the last part of a path without having to call the external basename:

dir="/path/to/whatever/"
dir="${dir%/}"             # strip trailing slash (if any)
subdir="${dir##*/}"

This uses Bash's parameter expansion to remove the part of the string before the last (remaining) slash.

Upvotes: 106

Mostafa Wael
Mostafa Wael

Reputation: 3846

To print the file name without using external commands,

Run:

fileNameWithFullPath="${fileNameWithFullPath%/}";
echo "${fileNameWithFullPath##*/}" # print the file name

This command must run faster than basename and dirname.

Upvotes: 2

Jingguo Yao
Jingguo Yao

Reputation: 8006

The following approach can be used to get any path of a pathname:

some_path=a/b/c
echo $(basename $some_path)
echo $(basename $(dirname $some_path))
echo $(basename $(dirname $(dirname $some_path)))

Output:

c
b
a

Upvotes: 162

Related Questions