Cut folder names out of string

How do I extract the folder named test from the following string?

TRUE|/home/linux/test|(null)|
Asked By: scotty030253

||

If you would like to get "Extra credit" for your assignment, Then use awk

echo 'TRUE|/home/linux/test|(null)|' | awk -F '[|/]' '{print $5}'

The awk option -F defines the field separator(s). When enclosed in brackets [|/] defines both | and / as a field separator. So "test" would be the fifth argument '{print $5}'

Answered By: stumblebee

Bash has a very easy way to match elements of a path (as long as your path is defined as a variable) with parameter expansion.

Using the ${parameter##word} construct, you search from the beginning of the line, and deletes everything up until the last match. In the case of a path, this will remove everything but the last directory, like this:

path='/path/to/my/stuff'; echo ${path##*/}

Output:

stuff

In your case though, you’ll still have the final part |(null)| to get rid off. In this particular case, you could do a double parameter expansion, like this:

path='TRUE|/home/linux/test|(null)|'; path=${path##*/}; echo ${path%%|*}

Output:

test

So in this case, you first match from the beginning to the last / (using ${path##*/}), and then match from the end to the last | (using ${path%%|*}).

In this way, you can perform a lot of string manipulation by using only Bash builtin functionality.

Answered By: Artur Meinild

There are already two working solutions here, but I just wanted to also point out the following method, which maybe maps onto the imperative mindset more.

echo 'TRUE|/home/linux/test|(null)|' | awk -F '|' '{print $2}' | xargs basename

Conceptually, we 1) get the second element of the input, and 2) get the basename of that path.

awk -F '|' '{print $2}' splits on the | character, and gives you the second element, which would be /home/linux/test. Then, you want extract test from the given path, which is what the basename command does. The additional xargs is annoying from an aesthetic perspective, but is necessary because (as far as I am aware) the basename command can’t read paths from stdin.

As user @Ray points out in their comment, cut would also work just as well as awk in this same solution.

Answered By: Pacopenguin

It’s not really clear from your question if you want to get the third item of an absolute path or if you want to get the last item of an absolute path.

  • If you want to get the third item of an absolute path, you can also use the following command that makes use of tr and cut:

    echo 'TRUE|/home/linux/test|(null)|' | tr '|' '/' | cut -d '/' -f 5
    

    tr '|' '/' converts | to /, then cut -d '/' -f 5 uses / as delimiter (-d '/') and outputs the 5th element (-f 5).

  • If you want to get the last item of an absolute path using tr and cut in a way similar to the above, you can also make use of the rev command as follows:

    echo 'TRUE|/home/linux/test|(null)|' | tr '|' '/' | rev | cut -d '/' -f 3 | rev
    

    tr '|' '/' converts | to /, then the first rev reverses the string,
    cut -d '/' -f 3 uses / as delimiter (-d '/') and outputs the 3rd element (-f 3), and finally the second rev reverses the string again.


References

Answered By: BeastOfCaerbannog

Oh okay, here is a sed answer

$ echo 'TRUE|/home/linux/test|(null)|' | sed -r 's#.*/([^|]+)|.*#1#'
test

Explanation:

  • -r use extended regex
  • s#...#..# find and replace using # as an alternative delimiter to /
  • .*/ any number of any characters before / including / (consumes all the /s leaving only whatever follows the last one)
  • ([^|]+) save some characters that are not | to use later
  • |.* | and whatever follows it (| is a special character, hence escaped – not needed in [ ] character classes)
  • 1 the saved pattern
Answered By: Zanna
Categories: Answers Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.