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

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

Follow

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
CleverLibre Social

CleverLibre Social is an inclusive social instance for open discussion, learning, and community.
All cultures welcome.
Hate speech and harassment strictly forbidden.