Home > Software engineering >  How to remove all file extensions in bash?
How to remove all file extensions in bash?

Time:12-14

x=./gandalf.tar.gz
noext=${x%.*}
echo $noext

This prints ./gandalf.tar, but I need just ./gandalf. I might have even files like ./gandalf.tar.a.b.c which have many more extensions.

I just need the part before the first .

CodePudding user response:

If you want to give sed a chance then:

x='./gandalf.tar.a.b.c'
sed -E 's~(.)\..*~\1~g' <<< "$x"

./gandalf

Or 2 step process in bash:

x="${s#./}"
echo "./${x%%.*}"

./gandalf

CodePudding user response:

If performance is not an issue, for instance something like this:

fil=$(basename "$x")
noext="$(dirname "$x")"/${fil%%.*}

CodePudding user response:

Strip the path first, then use greedy cancellation.

x=./gandalf.tar.gz
nopath=${x##*/}
noext=${nopath%%.*}

Edit: I just realized that you want the path in the outcome. Perhaps a regexp is the best way to go (if your bash version supports it):

[[ "$x" =~ ^(.*/|)(.[^.]*).*$ ]] && noext="${BASH_REMATCH[1]}${BASH_REMATCH[2]}"

Edit 2: I forgot to explain the regexp.

The first group captures everything up to the last / included (regexp are greedy in bash), or nothing if there are no / in the string. Then the second group captures everything up to the first ., excluded.

The rest of the string is not captured, as we want to get rid of it.

Finally, we concatenate the path and the stripped name.

Edit 3: it's not clear what you want to do with files beginning with a . (hidden files). I modified the regexp to preserve that . if present, as it seemed the most reasonable thing to do. E.g.

x="/foo/bar/.myinitfile.sh"

becomes /foo/bar/.myinitfile.

  • Related