Latest LQ Deal: Complete CCNA, CCNP & Red Hat Certification Training Bundle
Go Back > Forums > Linux Forums > Linux - Newbie
User Name
Linux - Newbie This Linux forum is for members that are new to Linux.
Just starting out and have a question? If it is not in the man pages or the how-to's this is the place!


  Search this Thread
Old 04-12-2012, 01:16 PM   #1
LQ Newbie
Registered: Apr 2012
Posts: 2

Rep: Reputation: Disabled
extract directory name from path in script

I'm trying to write a script to automate some analysis of some stuff I do for work. The system passes on a path from an earlier step in the form of an environment variable that I need. However, what I need is a directory further up the path, not the full path, so I would like to extract that directory name.

Here is an example of the information that's passed: /data/R_2012_03_20_22_03_14_FLX03090507_Administrator_AA14-17_21-22_HLA1_4/D_2012_03_20_22_05_21_FLX03090507_imageProcessingOnlyAmplicons/regions/

What I need is the directory beginning with R (R_2012_03_20_22_03_14_FLX03090507_Administrator_AA14-17_21-22_HLA1_4). I need this so that I can search that directory for a group of files to copy to another location. Finding those files and copying them isn't a problem, I just need to tell it where to look.
Old 04-12-2012, 01:23 PM   #2
LQ Guru
Registered: May 2005
Location: Atlanta Georgia USA
Distribution: Redhat (RHEL), CentOS, Fedora, CoreOS, Debian, FreeBSD, HP-UX, Solaris, SCO
Posts: 7,134
Blog Entries: 14

Rep: Reputation: 1265Reputation: 1265Reputation: 1265Reputation: 1265Reputation: 1265Reputation: 1265Reputation: 1265Reputation: 1265Reputation: 1265
echo $VAR |awk -F/ '{print $3}'
Where $VAR is the name of the variable that contains the path.

Note the awk strips the "/" from each component of the path (because it is being told to use that as a field separator) including the first one so if you need that you might set it by adding it back in the print:

echo $VAR |awk -F/ '{print "/"$3}'
Also be aware of dirname and basename commands. The former gives you the path to the file (entire path without the file name at end) and the latter gives you just the file name at the end of the path.

Last edited by MensaWater; 04-12-2012 at 01:26 PM.
Old 04-12-2012, 01:26 PM   #3
LQ Guru
Registered: Sep 2003
Location: Bologna
Distribution: CentOS 6.5 OpenSuSE 12.3
Posts: 10,509

Rep: Reputation: 1978Reputation: 1978Reputation: 1978Reputation: 1978Reputation: 1978Reputation: 1978Reputation: 1978Reputation: 1978Reputation: 1978Reputation: 1978Reputation: 1978
If it is the only item in the path beginning with R, you can try something like this:
$ VAR=/data/R_2012_03_20_22_03_14_FLX03090507_Administrator_AA14-17_21-22_HLA1_4/D_2012_03_20_22_05_21_FLX03090507_imageProcessingOnlyAmplicons/regions/
$ echo $VAR | sed -r 's:.*/(R[^/]+)/.*:\1:'
On the other hand, if it is always the item after /data, using awk will be easier:
$ echo $VAR | awk -F/ '{print $3}'
Old 04-12-2012, 02:01 PM   #4
LQ Guru
Registered: Sep 2009
Location: Perth
Distribution: Manjaro
Posts: 9,579

Rep: Reputation: 2914Reputation: 2914Reputation: 2914Reputation: 2914Reputation: 2914Reputation: 2914Reputation: 2914Reputation: 2914Reputation: 2914Reputation: 2914Reputation: 2914
Well I can think of 2 ways in bash:

#1 Assuming directory is always after /data

echo "${dir1%%/*}"

#2 Assuming it could be anywhere in the path but the first one starting with an 'R'

[[ $VAR =~ $match ]] && dir2=${BASH_REMATCH[1]}

echo "$dir2"
And an alternate awk solution (using same VAR):
echo "$VAR" | awk 'NR == 3' RS="/"

Last edited by grail; 04-12-2012 at 02:04 PM.
Old 04-12-2012, 07:14 PM   #5
LQ Newbie
Registered: Apr 2012
Posts: 2

Original Poster
Rep: Reputation: Disabled
Thanks guys. It seems there are several ways to do it. I tried a few of the suggestions and got it work just as I want it to.

The variety of suggestions is good for me as well because I can study them to understand how they work and learn something about how the various tools work.
1 members found this post helpful.
Old 04-12-2012, 07:18 PM   #6
LQ Guru
Registered: Aug 2004
Location: Sydney
Distribution: Centos 6.9, Centos 7.3
Posts: 17,418

Rep: Reputation: 2398Reputation: 2398Reputation: 2398Reputation: 2398Reputation: 2398Reputation: 2398Reputation: 2398Reputation: 2398Reputation: 2398Reputation: 2398Reputation: 2398
Just as another way (assuming its always 2nd dir as above)
echo /dat/rdir/ddir |cut -d'/' -f3
Old 04-13-2012, 12:32 PM   #7
David the H.
Bash Guru
Registered: Jun 2004
Location: Osaka, Japan
Distribution: Debian + kde 4 / 5
Posts: 6,837

Rep: Reputation: 1983Reputation: 1983Reputation: 1983Reputation: 1983Reputation: 1983Reputation: 1983Reputation: 1983Reputation: 1983Reputation: 1983Reputation: 1983Reputation: 1983
See this link for a long list of built-in bash string manipulations. Your challenge here is to split up the string into individual directory elements, and output only the ones you want. In addition to the suggestions grail gave above, you could use an array, or read, and perhaps a few others.

Here's a quick example function I just wrote up using an array:

     #print an arbitrary number of levels from a given file path
     #$1 is the path, $2 is the number of levels to print

     local IFS='/'
     local -a path=( $1 )

     echo "/${path[*]:1:$2}"


$ extractpath "/home/david/temp/test/foo/bar/baz" 4
And here's an example of how to use read (and a here string to pass the pathname to it):

$ IFS='/' read _ a b c d e _ <<<"/home/david/temp/test/foo/bar/baz"
$ echo "/$a/$b/$c/$d/$e"
Note that you could also just use read's -a option to load an array instead.

Also notice that when IFS is set to anything other than whitespace, then the empty string in front of the first delimiter is treated as the first entry. That's why the echoing of the array in the function starts with field 1, and the disposable "_" variable is included at the start in the read command (as well as at the end, where it catches all the trailing fields we don't want).

Finally, one more way to grab arbitrary numbers of levels, using parameter expansion:

$ fullpath='/home/david/temp/test/foo/bar/baz/'
$ keeppath="${fullpath#/*/*/*/}"	#use the desired number of /*/ levels you want to keep
$ echo "${fullpath%$keeppath}"
Be careful with this one though. The exact pattern you need to use depends on whether the fullpath has a trailing slash or not.

Last edited by David the H.; 04-13-2012 at 12:42 PM.


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off

Similar Threads
Thread Thread Starter Forum Replies Last Post
shell script is defined in someother directory, how it is being invoked with path? vaibhavs17 Linux - Newbie 2 05-30-2011 11:24 PM
[SOLVED] Shell Script - Use variable in a for loop with directory path Tech109 Linux - General 2 01-19-2011 11:22 AM
Script cannot find directory path mike2008 Linux - Newbie 7 04-29-2009 01:12 PM
Shell script help: How to pass a directory path to the script? dv502 Programming 13 09-10-2008 04:07 AM
Discovering Script Directory Path WayneK Programming 9 07-14-2008 10:18 AM > Forums > Linux Forums > Linux - Newbie

All times are GMT -5. The time now is 11:17 PM.

Main Menu
Write for LQ is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Facebook: linuxquestions Google+: linuxquestions
Open Source Consulting | Domain Registration