Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

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:

/VPfig/Amer/AR4/Celtel/files/COM.txt
share|improve this question

3 Answers 3

up vote 5 down vote accepted

Try:

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

which gave me:

/VPfig/Amer/AR4/Celtel/files/COM.txt

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 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 at 13:19

In a POSIX shell:

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

Explanation

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/^\/[^/]*//'
/VPfig/Amer/AR4/Celtel/files/COM.txt

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]'
/VPfig/Amer/AR4/Celtel/files/COM.txt

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#/[^/]+/#/#'
/VPfig/Amer/AR4/Celtel/files/COM.txt

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/.*'
/VPfig/Amer/AR4/Celtel/files/COM.txt
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 at 11:07
    
@JosephR. yes it should, thanks. Answer edited. –  terdon Jul 17 at 11:19

Your Answer

 
discard

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.