Juergen
Juergen

Reputation: 3743

How to remove all file extensions in bash?

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 .

Upvotes: 1

Views: 123

Answers (4)

David
David

Reputation: 196

Perhaps a regexp is the best way to go if your bash version supports it, as it doesn't fork new processes.

This regexp works with any prefix path and takes into account files with a dot as first char in the name (hidden files):

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

Regexp explained

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.

Note

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.

Upvotes: 1

M. Nejat Aydin
M. Nejat Aydin

Reputation: 10123

Using extglob shell option of bash:

shopt -s extglob
x=./gandalf.tar.a.b.c
noext=${x%%.*([!/])}
echo "$noext"

This deletes the substring not containing a / character, after and including the first . character. Also works for x=/pq.12/r/gandalf.tar.a.b.c

Upvotes: 2

user1934428
user1934428

Reputation: 22225

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

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

Upvotes: 0

anubhava
anubhava

Reputation: 784938

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

Upvotes: 3

Related Questions