RandomCoder
RandomCoder

Reputation: 99

Replace directory names in a path in ksh script

I want to produce a relative path from a given absolute path and store it in a variable.

/aaa/bbb/ccc/ddd/eee.txt should be producing ../../../.. which I can append to some other path as per the requirement.

$filepath=/aaa/bbb/ccc/ddd/eee.txt

I want to create a new variable called $abs which shall contain ../../../...

Tried this:

echo "$filepath" | sed -r 's/*/../g'

The above-said template is not working as per the requirement.

Being a newbie I might be asking foolish question.

Please excuse and thanks in advance!

Upvotes: 1

Views: 150

Answers (2)

Walter A
Walter A

Reputation: 20002

You can avoid escaping slashes with another character like #.
First you cut off the filename from the path with "${filepath%/*}" (better than basename).
You replace every string with at least one character by dots.
And finally remove the starting slash.

echo "${filepath%/*}"| sed 's#[^/]\+#...#g;s#\/##'

Upvotes: 1

lw0v0wl
lw0v0wl

Reputation: 674

I am not sure sed is capable of this but, can show an awk command that do it.

echo "$filepath" | awk -F'/' '{ for ( i = 2; i < NF-1; i++ ) printf "../" } END{print ".."}'

where -F '/' is the field separator is separate the text /aaa/bbb/ccc/ddd/eee.txt into 6 sections, each section is can be used as a variable in awk, this also cause it remove field separator / in this case, from the text.

  • $1 is '' empty as first / not have anything before it.
  • $2 is aaa
  • $3 is bbb
  • $4 is ccc
  • $5 is ddd
  • $6 is eee.txt

NF variable contain how many field we have.


for ( i = 2; i < NF-1; i++ ) is for cycle

I start at 2 instead of 1 as first field is always empty, cause absolute path always start with / , this will ignore that field.

I also subtract NF variable with 1 as last field, will contain the file name, hence it is not a directory, however this allow a issue to happen if it is a directory and there is no / at the end of it like /home/jondoe you will end with .. instead of ../.. while /home/jondoe/ will work.

printf "../" get printed next to each other in each cycle as long for cycle is go.

END{print ".."} will print .. regardless what happened is the input. This will cause the .. at the end of the text while for cycle only print ../ repeatedly


This command still can be improved to eliminate pitfalls, like the one I mentioned. I hope this suit your needs.

Upvotes: 1

Related Questions