Shell command to remove files extension

$ touch {a,b,c,"white space"}.sample

$ ls *.sample
a.sample        c.sample
b.sample        white space.sample

$ for SAMPLE in *.sample; do mv -v "$SAMPLE" "${SAMPLE%.sample}"; done
a.sample -> a
b.sample -> b
c.sample -> c
white space.sample -> white space

Edit: Also see ${parameter#word}, which deletes word from the front of parameter:

$ FILENAME=140909_stats_report.txt
$ echo "${FILENAME#140909_}"
stats_report.txt

I remember which of these I need from the positions of the # and % keys on my (UK) keyboard: # is left of % so matches on the left. Before I noticed that I had to check the man page every time :~)

These expansions also support shell wildcards:

$ echo "${FILENAME%.*}"
140909_stats_report

The # and % forms match the shortest expansion of word. You can use ## or %% for the longest match. E.g.:

$ FILENAME=140909_stats_report.txt
$ echo "${FILENAME#*_}"  # match as little as possible
stats_report.txt
$ echo "${FILENAME##*_}" # match as much as possible
report.txt

It's worth getting to grips with these expansions. There's several more, including (somewhat cranky) regex support, substrings and ways to set defaults or get variable lengths. Man bash, of course.


for n in *.sample ; do mv "$n" "$(basename "$n" .sample)" ; done