6

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?

  • 1
    Where are you getting the number in your renamed file from? Is it at the end of the .A2010001. part of the original filename? Is there a chance that any of these number strings will have duplicate values? – Arronical Nov 21 '17 at 10:37
  • .A2010001... .A2010365 is for 1...365 files. – Vaishali Jain Nov 21 '17 at 10:41
  • 2
    If the glob MOD*.hdf is not returning any results your filenames must not be in the format you've stated, or you're not in the directory containing the files. – Arronical Nov 21 '17 at 10:51
  • 1
    The question Zanna asked is still not answered by OP and it is important as it will change the suggested answer. The question I have is whether the number 1 to 365 in .A2010001...A2010365 must be used in the new file name. If so, the suggested answer below will not suffice. – user680858 Nov 21 '17 at 11:00
  • 2
    Those aren't complex numbers, just plain old integers! – ilkkachu Nov 21 '17 at 18:40
10

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.

  • How does the (\d+) capture the numbers? Is it regex magic? – Arronical Nov 21 '17 at 11:35
  • 4
    @Arronical \d is any digit in Perl regex, the () is a capture group, and the preceding 0* takes all the leading zeros – muru Nov 21 '17 at 11:37
  • Marvellous, thanks for expanding my knowledge as always! – Arronical Nov 21 '17 at 11:41
  • @Arronical \d simply is a shorthand for [0-9], those shorthands are supported quite universally – for more see regular-expressions.info. – dessert Nov 21 '17 at 12:00
  • 1
    @dessert universally is a bit too broad, sed and awk don't, grep needs -P (for Perl-compatible RE)... – muru Nov 22 '17 at 1:49
6

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.

  • Just noticed you removed the syntax highlighting on purpose – may I ask why? The community's opinion on this seems to be quite clear… – dessert Nov 21 '17 at 15:35
6

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 replace old with new
  • \. literal .
  • ... three characters that could be anything
  • (some chars) save some 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 rename to create the names you actually asked for... if I do, I will update my answer muru's answer does that...).

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
5

The below code will do the following:

  1. loop over all files which starts with MOD and ends with .hdf
  2. Assign a variable, which will increase its value in 1 for every file
  3. perform the mv command on the current file in the list and change its name to modis follows by the number from the variable, follows the the .hdf

    #!/bin/bash 
    idx=1
    for file in MOD*.hdf
    do
        echo mv "$file" "modis$((idx++)).hdf"
    done
    

Note: the above script will only echo the command it plan to perform, you'll need to remove the echo from the echo mv line in order to perform the action action.

Sample output:

mv MOD11A1.A2010001.h24v06.006.2016025150444.hdf modis1.hdf
mv MOD11A1.A2010002.h24v06.006.2016025151748.hdf modis2.hdf
mv MOD11A1.A2010003.h24v06.006.2016025163706.hdf modis3.hdf
  • mv: cannot stat ‘MOD*.hdf’: No such file or directory error is showing in terminal. – Vaishali Jain Nov 21 '17 at 10:46
  • how to use rename command for achieving my purpose? – Vaishali Jain Nov 21 '17 at 10:49
  • 1
    @VaishaliJain - did you execute the above lines of code, in the folder which actually holds the MOD11A1... files? – Yaron Nov 21 '17 at 10:51
  • @VaishaliJain - mv is a rename command – Yaron Nov 21 '17 at 10:53
  • @pa4080 thanks for your comment! Will update my answer once I'll be near a computer. – Yaron Nov 21 '17 at 19:39

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.