How to rename with prefix/suffix?
BashRenameFilenamesPrefixMvBash 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