Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

Please advise on how to remove the first directory from a path by sed, (the inverse pf what basename does).

For example

echo "/mnt/VPfig/Amer/AR4/Celtel/files/COM.txt" | sed ...

I should get:

share|improve this question
up vote 5 down vote accepted


echo "/mnt/VPfig/Amer/AR4/Celtel/files/COM.txt" | sed 's|^/[^/]*||'

which gave me:


It looks for the first / followed by as many non-/s as possible, then replaces them with an empty string.

share|improve this answer
Is there need to escape? sed 's,^/[^/]*,,' works fine to me. – fedorqui Jul 17 '14 at 13:11
Probably not - I tend to escape and quote everything to be on the safe side :-) I'll edit it. – garethTheRed Jul 17 '14 at 13:19

In a POSIX shell:

$ x='/mnt/VPfig/Amer/AR4/Celtel/files/COM.txt'
$ printf "/%s\n" "${x#/*/}"


The parameter expansion ${x#/*/} removes the leading component of the path with the two /s enclosing it and the printf tacks a leading / back on.

share|improve this answer

The simplest way would be to remove the shortest string of non-/ characters from the beginning of the string.

In most regular expression languages, [ ] os a character class that matches anything within the brackets. [abc] will match either a or b or c. [^ ] is a negated character class, matching anything except the characters in it. So, [^/]* will match the longest string of non-/ characters. A ^ at the beginning of a regular expression makes it match only at the beginning of the input string. Combining these, you can do:

$ echo "/mnt/VPfig/Amer/AR4/Celtel/files/COM.txt" | sed 's/^\/[^/]*//'

Or, you can set the input field delimiter of awk to / and print everything but the last field:

$ echo "/mnt/VPfig/Amer/AR4/Celtel/files/COM.txt" | 
    awk -F/ '{for(i=3;i<=NF;i++){printf "/%s",$i};print ""}'

Or you could use some Perl trickery:

$ echo "/mnt/VPfig/Amer/AR4/Celtel/files/COM.txt" | 
    perl -F/ -lane 'print "/",join "/",@F[2..$#F]'

or, some better Perl trickery as suggested by @Joseph R.:

$ echo "/mnt/VPfig/Amer/AR4/Celtel/files/COM.txt" | perl -pe 
   perl -pe 's{^/.*?(?=/)}{}'

or even simply:

$ echo "/mnt/VPfig/Amer/AR4/Celtel/files/COM.txt" | perl -pe 's#/[^/]+/#/#'

Finally, you could also use the power of Perl regular expressions with grep:

$ echo "/mnt/VPfig/Amer/AR4/Celtel/files/COM.txt" | grep -oP '/[^/]+?\K/.*'
share|improve this answer
Shouldn't the Perl trickery just make use of the superior Perl regexes? echo ... | perl -pe 's{^/.*?(?=/)}{}' – Joseph R. Jul 17 '14 at 11:07
@JosephR. yes it should, thanks. Answer edited. – terdon Jul 17 '14 at 11:19

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.