I need 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:



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.

  • 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

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/.*'
  • 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

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.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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