How to rename with prefix/suffix?

BashRenameFilenamesPrefixMv

Bash Problem Overview


How do I do mv original.filename new.original.filename without retyping the original filename?

I would imagine being able to do something like mv -p=new. original.filename or perhaps mv original.filename new.~ or whatever - but I can't see anything like this after looking at man mv / info mv pages.

Of course, I could write a shell script to do this, but isn't there an existing command/flag for it?

Bash Solutions


Solution 1 - Bash

You could use the rename(1) command:

rename 's/(.*)$/new.$1/' original.filename

Edit: If rename isn't available and you have to rename more than one file, shell scripting can really be short and simple for this. For example, to rename all *.jpg to prefix_*.jpg in the current directory:

for filename in *.jpg; do mv "$filename" "prefix_${filename}"; done;

or also, leveraging from Dave Webb's answer and using brace expansion:

for filename in *.jpg; do mv {,prefix_}"$filename"; done;

Solution 2 - Bash

In Bash and zsh you can do this with Brace Expansion. This simply expands a list of items in braces. For example:

# echo {vanilla,chocolate,strawberry}-ice-cream
vanilla-ice-cream chocolate-ice-cream strawberry-ice-cream

So you can do your rename as follows:

mv {,new.}original.filename

as this expands to:

mv original.filename new.original.filename

Solution 3 - Bash

You can achieve a unix compatible multiple file rename (using wildcards) by creating a for loop:

for file in *; do
  mv $file new.${file%%}
done

Solution 4 - Bash

I've seen people mention a rename command, but it is not routinely available on Unix systems (as opposed to Linux systems, say, or Cygwin - on both of which, rename is an executable rather than a script). That version of rename has a fairly limited functionality:

rename from to file ...

It replaces the from part of the file names with the to, and the example given in the man page is:

rename foo foo0 foo? foo??

This renames foo1 to foo01, and foo10 to foo010, etc.

I use a Perl script called rename, which I originally dug out from the first edition Camel book, circa 1992, and then extended, to rename files.

#!/bin/perl -w
#
# @(#)$Id: rename.pl,v 1.7 2008/02/16 07:53:08 jleffler Exp $
#
# Rename files using a Perl substitute or transliterate command

use strict;
use Getopt::Std;

my(%opts);
my($usage) = "Usage: $0 [-fnxV] perlexpr [filenames]\n";
my($force) = 0;
my($noexc) = 0;
my($trace) = 0;

die $usage unless getopts('fnxV', \%opts);

if ($opts{V})
{
    printf "%s\n", q'RENAME Version $Revision: 1.7 $ ($Date: 2008/02/16 07:53:08 $)';
    exit 0;
}
$force = 1 if ($opts{f});
$noexc = 1 if ($opts{n});
$trace = 1 if ($opts{x});

my($op) = shift;
die $usage unless defined $op;

if (!@ARGV) {
    @ARGV = <STDIN>;
    chop(@ARGV);
}

for (@ARGV)
{
    if (-e $_ || -l $_)
    {
        my($was) = $_;
        eval $op;
        die $@ if $@;
        next if ($was eq $_);
        if ($force == 0 && -f $_)
        {
            print STDERR "rename failed: $was - $_ exists\n";
        }
        else
        {
            print "+ $was --> $_\n" if $trace;
            print STDERR "rename failed: $was - $!\n"
                unless ($noexc || rename($was, $_));
        }
    }
    else
    {
        print STDERR "$_ - $!\n";
    }
}

This allows you to write any Perl substitute or transliterate command to map file names. In the specific example requested, you'd use:

rename 's/^/new./' original.filename

Solution 5 - Bash

I know there is great answers here but I found no reference to handle filename extensions when adding suffix.

I needed to add '_en' suffix to all wav files in a folder before the file extension.

The magic is here: %.*

for filename in *.wav; do mv $filename ${filename%.*}_en.wav; done;

If you need to handle different file extensions, check this answer. A bit less intuitive.

Solution 6 - Bash

The easiest way to bulk rename files in directory is:

ls | xargs -I fileName mv fileName fileName.suffix

Solution 7 - Bash

If it's open to a modification, you could use a suffix instead of a prefix. Then you could use tab-completion to get the original filename and add the suffix.

Otherwise, no this isn't something that is supported by the mv command. A simple shell script could cope though.

Solution 8 - Bash

In my case I have a group of files which needs to be renamed before I can work with them. Each file has its own role in group and has its own pattern.

As result I have a list of rename commands like this:

f=`ls *canctn[0-9]*`   ;  mv $f  CNLC.$f
f=`ls *acustb[0-9]*`   ;  mv $f  CATB.$f
f=`ls *accusgtb[0-9]*` ;  mv $f  CATB.$f
f=`ls *acus[0-9]*`     ;  mv $f  CAUS.$f

Try this also :

f=MyFileName; mv $f {pref1,pref2}$f{suf1,suf2}

This will produce all combinations with prefixes and suffixes:

pref1.MyFileName.suf1
...
pref2.MyFileName.suf2

Another way to solve same problem is to create mapping array and add corespondent prefix for each file type as shown below:

#!/bin/bash
unset masks
typeset -A masks
masks[ip[0-9]]=ip
masks[iaf_usg[0-9]]=ip_usg
masks[ipusg[0-9]]=ip_usg
...
for fileMask in ${!masks[*]}; 
do  
registryEntry="${masks[$fileMask]}";
fileName=*${fileMask}*
[ -e ${fileName} ] &&  mv ${fileName} ${registryEntry}.${fileName}  
done

Solution 9 - Bash

Bulk rename files bash script

#!/bin/bash
# USAGE: cd FILESDIRECTORY; RENAMERFILEPATH/MultipleFileRenamer.sh FILENAMEPREFIX INITNUMBER
# USAGE EXAMPLE: cd PHOTOS; /home/Desktop/MultipleFileRenamer.sh 2016_
# VERSION: 2016.03.05.
# COPYRIGHT: Harkály Gergő | mangoRDI (https://wwww.mangordi.com/) 

# check isset INITNUMBER argument, if not, set 1 | INITNUMBER is the first number after renaming
if [ -z "$2" ]
	then i=1;
else
	i=$2;
fi

# counts the files to set leading zeros before number | max 1000 files
count=$(ls -l * | wc -l)
if [ $count -lt 10 ]
	then zeros=1;
else
	if [ $count -lt 100 ]
		then zeros=2;
	else
		zeros=3
	fi
fi

# rename script
for file in *
do
	mv $file $1_$(printf %0"$zeros"d.%s ${i%.*} ${file##*.})
	let i="$i+1"
done

Solution 10 - Bash

I don't like any of the other answers.
My take is that you want a vanilla bash solution. So here you go!

Try this with echo first to see what is going to happen!
Test your command before you use it on thousands of files!

Remove the './' if you want to put in a prefix
find . -type f -exec bash -c 'echo prefix_${0#./}' {} \;

In the question asked, prefix_ is new. so the command becomes
find . -type f -exec bash -c 'echo mv $0 new.${0#./}' {} \;

Remove the extension if you want to put something after it
find . -type f -exec bash -c 'echo ${0%.*}_suffix.${0##*.}' {} \;

Now to use this to rename just replace echo with mv $0.

EXAMPLE:
find . -type f -exec bash -c 'mv $0 1.${0#./}' {} \;

Inspired by: https://gist.github.com/larshaendler/723d2ec447c3c694b71dc6e3bc3aadc9

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionPeter BoughtonView Question on Stackoverflow
Solution 1 - BashSimon LehmannView Answer on Stackoverflow
Solution 2 - BashDave WebbView Answer on Stackoverflow
Solution 3 - BashA MuguroView Answer on Stackoverflow
Solution 4 - BashJonathan LefflerView Answer on Stackoverflow
Solution 5 - BashyeyaView Answer on Stackoverflow
Solution 6 - BashBrajan ElektroView Answer on Stackoverflow
Solution 7 - Bashworkmad3View Answer on Stackoverflow
Solution 8 - BashaprodanView Answer on Stackoverflow
Solution 9 - BashHarkály GergőView Answer on Stackoverflow
Solution 10 - BashbotenvouwerView Answer on Stackoverflow