Renaming multiple files with complex numbered names
I have 365 files named
MOD11A1.A2010001.h24v06.006.2016025150444.hdf
MOD11A1.A2010002.h24v06.006.2016025151748.hdf
MOD11A1.A2010003.h24v06.006.2016025163706.hdf
and I want to rename these files as:
modis1.hdf
modis2.hdf
modis3.hdf
I am using the mv
command separately for each file to rename them.
How do I achieve this in one go?
Since you only care about the A2010...
bit, using rename
in the directory with the files:
rename -n 's/.*A2010*(\d+).*/modis$1.hdf/' *
Example:
$ rename -n 's/.*A2010*(\d+).*/modis$1.hdf/' *
rename(> MOD11A1.A2010001.h24v06.006.2016025150444.hdf, modis1.hdf)
rename(> MOD11A1.A2010002.h24v06.006.2016025151748.hdf, modis2.hdf)
rename(> MOD11A1.A2010003.h24v06.006.2016025163706.hdf, modis3.hdf)
rename(> MOD11A1.A2010365.h24v06.006.2016025150444.hdf, modis365.hdf)
Run without -n
to actually rename the files.
The following way uses bash parameter expansion, but it does rely on your filenames being in exactly the format you've stated as it relies on the placement of the numeric string to be used. This isn't necessarily the most robust method. You must also be in the directory containing the files.
for f in MOD*.hdf; do
num="${f:13:3}"
mv "$f" modis"$((10#$num))".hdf
done
Or as a one-liner:
for f in MOD*.hdf; do num="${f:13:3}"; mv "$f" modis"$((10#$num))".hdf ; done
This will move the files in the manner which you've asked for, meaning that MOD11A1.A2010001.h24v06.006.2016025150444.hdf
will become modis1.hdf
, MOD11A1.A2010002.h24v06.006.2016025151748.hdf
becomes modis2.hdf
etc.
You could use the rename
command like this:
$ rename -n 's/MOD11A1\.A2010(...)\..*/modis$1.hdf/' MOD*.hdf
rename(MOD11A1.A2010001.h24v06.006.2016025150444.hdf, modis001.hdf)
rename(MOD11A1.A2010002.h24v06.006.2016025151748.hdf, modis002.hdf)
rename(MOD11A1.A2010003.h24v06.006.2016025163706.hdf, modis003.hdf)
After testing, remove -n
to actually rename files.
Notes
-
s/old/new
replaceold
withnew
-
\.
literal.
-
...
three characters that could be anything -
(some chars)
savesome chars
to reference later with$1
- We could use a simple regex to match the first part of the filename in the
rename
command, as muru's answer does. Sometimes you want to use a more explicit expression to distinguish between files that you do or don't want to act on, or to be sure that your regex won't suck up too many characters. There's usually a lot of flexibility in solving this kind of problem.
Note that this doesn't give you exactly what you asked for; it maintains the fixed width of the numbers. I have done this because it's a good idea to use fixed-width numbers in filenames (otherwise they will be sorted in a confusing way, with 10 before 2, for example) (and because I haven't figured out how to use muru's answer does that...).rename
to create the names you actually asked for... if I do, I will update my answer
Note that Perl rename
is not included in the default 17.10 installation, so if you are running 17.10 (or for future readers, perhaps a later version), start by running
sudo apt install rename