Shahar
Shahar

Reputation: 501

Cut everything from specific char (or after) + Bash

I have files which all look like this: filename.bla_1

of cours I cannot know if the filename has "_" in it. could be file_name.bla_1. I want to write a function that take filename and delete the _# at the end. filename.bla_1 will be --> filename.bla

echo $filename | rev | cut -d "_" -f2 | rev

will do the trick if the file doesn't have "" in the name but I want to make sure this works also for filenames with ""

Upvotes: 0

Views: 46

Answers (3)

Paul Hodges
Paul Hodges

Reputation: 15273

If you care to tweak the globbing parser a little,

shopt -s extglob
for f in abc.bla a_b_c_.bla abc.bla_1 a_b_c_.bla_2 123.456.789 123.456.789_x abc_ 
do echo ${f%_+([^._])}
done
abc.bla
a_b_c_.bla
abc.bla
a_b_c_.bla
123.456.789
123.456.789
abc_

${f%_+([^._])} means the value of $f with a _ followed immediately by one or more non-dot-or-underscore characters trimmed OFF the end.

Upvotes: 1

choroba
choroba

Reputation: 241828

You can use parameter expansion. The % removes the shortest possible pattern on the right side of the value, ## removes the longest possible match on the left:

#! /bin/bash
for f in filename.bla_1 \
         file_name_with_underscores.foo_2 \
         file_name_with_underscores.foo \
         filename.with_dots.foo_2 ; do
    ext=${f##*.}
    basename=${f%.*}
    echo "$basename.${ext%_*}"
done

Upvotes: 6

glenn jackman
glenn jackman

Reputation: 246774

Use @choroba's answer.

But to fix your code, after you reverse the filename, you need to take the 2nd and all following fields, not just the 2nd:

$ filename=foo_bar_baz.bla_1
$ rev <<<"$filename" | cut -d_ -f2- | rev
foo_bar_baz.bla

The -f2- with the trailing hyphen is the magic here. Read the cut man page.

Upvotes: 0

Related Questions