25

I have a couple of files with ".old" extension.
How can I remove the ".old" extension without remove the file?

I can do it manually but with more work:

mv file1.key.old file1.key
mv file2.pub.old file2.pub
mv file3.jpg.old file3.jpg
mv file4.jpg.old file4.jpg

(etc...)

The command will work with other extensions too?

example:

mv file1.MOV.mov file1.MOV
mv file2.MOV.mov file2.MOV
mv file3.MOV.mov file3.MOV

(etc...)

or better:

mv file1.MOV.mov file1.mov
mv file2.MOV.mov file2.mov
mv file3.MOV.mov file3.mov

(etc...)
Gilles 'SO- stop being evil'
  • 807,993
  • 194
  • 1,674
  • 2,175
DiogoSaraiva
  • 465
  • 2
  • 5
  • 12

7 Answers7

31

Use bash's parameter substitution mechanism to remove matching suffix pattern:

for file in *.old; do
    mv -- "$file" "${file%%.old}"
done
Gilles 'SO- stop being evil'
  • 807,993
  • 194
  • 1,674
  • 2,175
jimmij
  • 46,064
  • 19
  • 123
  • 136
7

You didn't say what operating system you are using, but many Linux distributions have a rename command that you can use for this. There are actually two quite different rename commands - Debian and similar systems supply one while RedHat and similar supply another - but either one will work here.

Perl based rename on Debian, Ubuntu etc, see: prename manual.

Util-Linux rename on Redhat etc, see: rename manual.

On Debian and similar you can do:

rename 's/\.old$//' *

or:

rename s/.MOV.mov/.mov/ *.*

On Redhat and similar you can do:

rename .old "" *
kenorb
  • 20,250
  • 14
  • 140
  • 164
bdsl
  • 185
  • 3
4

There are a lot of multi rename tools like http://file-folder-ren.sourceforge.net/

But I think the fastest way to rename is a simple script like:

for i in *.old
do
   mv -- "$i" "${i%.old}"
done

Note there is no error checking and if the target file exists it might be overwritten.

Gilles 'SO- stop being evil'
  • 807,993
  • 194
  • 1,674
  • 2,175
Zaboj Campula
  • 1,116
  • 3
  • 15
  • 30
3

With zsh, first load the zmv function with

autoload zmv

(you can do this from your .zshrc) then run

zmv -w '*.old' '$1'

or

zmv '(*).old' '$1'
Gilles 'SO- stop being evil'
  • 807,993
  • 194
  • 1,674
  • 2,175
1

If you want to restrict answers to shell (Bash) programming (rather than using a renaming tool), try this:

for oldname in *.old ; do
    newname="${oldname%%.old}"
    if [ -e "$newname" ] ; then
        echo "Cannot rename $oldname because $newname exists." >&2
    else
        mv -- "$oldname" "$newname"
    fi
done

I use quotes around $oldname and $newname because filenames can contain blanks.

Gilles 'SO- stop being evil'
  • 807,993
  • 194
  • 1,674
  • 2,175
waltinator
  • 4,439
  • 1
  • 16
  • 21
-1

Assuming "file" does not contain a "." :

ls -1 | while read line; do mv "$line" "`echo $line | cut -d'.' -f1,2`"; done

This example splits the filename by period and with -f you can control the fields to keep.

For your third example, you would use:

ls -1 | while read line; do mv "$line" "`echo $line | cut -d'.' -f1,3`"; done
Volker Siegel
  • 16,983
  • 5
  • 52
  • 79
Christian Bock
  • 287
  • 2
  • 6
  • 1
    If your folder contains files that are not to be renamed, add `| grep ` after `ls -1` – Christian Bock Jan 21 '15 at 13:34
  • This removed more than I expected in file sub.class1.server.ca.pem.old become sub.class1 instead sub.class1.server.ca.pem Thanks – DiogoSaraiva Jan 21 '15 at 13:55
  • If it removed more than you expected, you failed to read the first line of my answer: _assuming "file" does not contain a ._ – Christian Bock Jan 21 '15 at 14:31
  • 2
    `ls | while read line; do …` has no advantage over `for line in *; do …` and the downside of breaking over various file names. [Do not parse the output of `ls`](http://mywiki.wooledge.org/ParsingLs). – Gilles 'SO- stop being evil' Jan 21 '15 at 22:38
-1

"Refinement" of Christian's solution ( https://unix.stackexchange.com/a/180275 ) using rev:

ls -1 | while read line; do mv "$line" "`echo $line | rev | cut -d'.' -f2- | rev`"; done