This one is super free! It is not a programming problem so much as a BASH problem.

Using bash parameter expansion only gnu.org/software/bash/manual/h

Given an arbitrarily long path, such as "/head/shoulders/knees/and/toes/eyes/ears/mouth" stored in a variable $TEMP construct a parameter expansion to render only the last two subdirectory and filename like "eyes/ears/mouth" such that you can simply offer the command "echo ${TEMP<stuff goes in here>}"

And yes I do know how much easier it is to do with grep, sed, python, perl, awk <insert your favorite alternate solution here> can do it better and easier. This is a real world problem, and someone on Reddit pointed me in the right direction.

Solution (with caveat) 

@Absinthe

The following _technically_ satisfies your requirements; in that I only replace the stuff in brackets from your example and doesn't use anything but parameter expansion.

However, there's a serious limitation I haven't figured out how to work around - it relies on knowing the name of the variable $TEMP. As stated the problem permits this, but that means I can't save my answer in a variable and reuse it like echo ${TEMP1<foo>}; echo ${TEMP2<foo>} without modifying <foo> in between.

echo ${TEMP#${TEMP%/**/**/**}}

Solution (with caveat) 

@khird close but that one still has the leading / on the output. Also, I don't think you need **, * will be sufficient. You are close :)

Solution (with caveat) 

@Absinthe

For some reason I had the idea the spec wanted the leading slash. This gets it without, but has the same caveat as the above.

echo ${TEMP#${TEMP%%+([^/])/+([^/])/+([^/])}}

Solution (with caveat) 

@khird
That gives the final path without any '/' at all ..

You were closer with the previous one

Follow

Solution (with caveat) 

@Absinthe Given your example where $TEMP="/head/shoulders/knees/and/toes/eyes/ears/mouth", it returns exactly "eyes/ears/mouth". Do you have a test case where it doesn't work?

Solution (with caveat) 

@khird I just typed this in and got this:

$ TEMP="/head/shoulders/knees/and/toes/eyes/ears/mouth"
$ echo ${TEMP#${TEMP%%+([^/])/+([^/])/+([^/])}}
eyes ears mouth

Solution (with caveat) 

@Absinthe Perhaps you have a bug in your version of Bash? That statetment involves two parameter manipulations - the inner removing a suffix and the outer removing a prefix. Neither of them should perform a character-replacement to print ' ' instead of '/'.

It works perfectly in Bash 4.3.11.

Solution (with caveat) 

@khird interestnig, it works at work, on 5.0.3 I will have to check the laptop again when I get home.

Consider this:
echo "${TEMP#${TEMP%/*/*/*}/}"

Solution (with caveat) 

@khird so I tried it in a new terminal window and it works. I tried it in the previous window and it still does it without the /'s funny that, but meh, almost with I could do that on purpose. But, anyway it works. Well done!

Sign in to participate in the conversation
Qoto Mastodon

QOTO: Question Others to Teach Ourselves
An inclusive, Academic Freedom, instance
All cultures welcome.
Hate speech and harassment strictly forbidden.