2

this is my firt question here. Thanks in advance.

I have automatically uploaded hundreds of images to a Webfaction server with an incorrect timestamp in the filename and now I have to rename them.

Here is an example:

  • tl0036_20161121-120558.jpg

  • myCode_yyyymmdd_hhmmss.jpg

I have to change the "hh" characters 1 hour back, so 12 should be 11. They are the 17th and 18th position. I imagine two ways of doing it:

  • Math operation: Images are taken from 1am to 11pm, so I see no problem in doing just a math operation like 12-1=11 for all of them.
  • Conditional: if 17th and 18th characters value are 12, then rename to 11. 24 conditions should be written, from 01 to 23 starting value.

I have found many answers here to replace/rename a fixed string and others about conditional operation, but nothing about my kind of mixed replacement.

Please I need advidce in how the script should be assuming it will be executed into the files folder. I am a novice used to work with bash or python.

Thank you!

Marc Torra
  • 21
  • 1

2 Answers2

0

Solution using datetime in Python

import time
import datetime

def change_filename(fn):

    # EXTRACT JUST THE TIMESTAMP AS A STRING
    timestamp_str = fn[7:22]

    # CONVERT TO UNIX TIMESTAMP
    timestamp = time.mktime(datetime.datetime.strptime(timestamp_str, "%Y%m%d-%H%M%S").timetuple())

    # SUBTRACT AN HOUR (3600 SECONDS)
    timestamp = timestamp - 3600

    # CHANGE BACK TO A STRING
    timestamp_str = datetime.datetime.fromtimestamp(timestamp).strftime("%Y%m%d-%H%M%S")

    # RETURN THE FILENAME WITH THE NEW TIMESTAMP
    return fn[:7] + timestamp_str + fn[22:]

This takes into account possible changes in the day, month, and year that could happen by putting the timestamp back an hour. If you're using a 12-hour time rather than 24 hour, you can use the format string "%Y%m%d-%I%M%S" instead; see the Python docs.

Credit to: Convert string date to timestamp in Python and Converting unix timestamp string to readable date in Python

This assumes that your myCode is of a fixed length, if not you could use the str.split method to pull out the hours from after the -, or if your filenames have an unknown number/placement of -s, you could look at using regular expressions to find the hours and replace them using capturing groups.

In Python, you can use a combination of glob and shutil.move to walk through your files and rename them using that function. You might want to use a regular expression to ensure that you only operate on files matching your naming scheme, if there are other files also in the directory/ies.

Naive Solution

With the caveats about the length of myCode and filename format as above.

If your timestamps are using the 24 hour format (00-23 hours), then you can replace the hours by subtracting one, as you say; but you'd have to use conditionals to ensure that you take care of turning 23 into 00, and take care of adding a leading zero to hours less than 10.

An example in Python would be:

def change_filename(fn):

    hh = int(fn[16:18])

    if hh == 0:
        hh = 23
    else:
        hh -= 1

    hh = str(hh)

    # ADD LEADING ZERO IF hh < 10
    if len(hh) == 1:
        hh = '0' + hh

    return fn[:16] + str(hh) + fn[18:]

As pointed out above, an important point to bear in mind is that this approach would not put the day back by one if the hour is 00 and is changed to 23, so you would have to take that into account as well. The same could happen for the month, and the year, and you'd have to take these all into account. It's much better to use datetime.

Community
  • 1
  • 1
Harry
  • 3,312
  • 4
  • 34
  • 39
0

For your file renaming logic, not only are you going to have issues over day boundaries, but also month, year, and leap-year boundaries. For example, if your filename is tl0036_20160101-000558.jpg, it needs to change to tl0036_20151231-230558.jpg. Another example: tl0036_20160301-000558.jpg will be tl0036_20160229-230558.jpg.

Creating this logic from scratch will be very time consuming - but luckily there's the datetime module in Python that has all this logic already built in.

Your script should consist of the following steps:

  1. Iterate through each '.jpg' file in your folder.
  2. Try to match your timestamp file name for each '.jpg'
  3. Extract the timestamp values and create a datetime.datetime object out of those values.
  4. Subtract a datetime.timedelta object equal to 1 hour from that datetime.datetime object, and set that as your new timestamp.
  5. Contstruct a new filename with your new timestamp.
  6. Replace the old filename with the new filename.

Here's an example implementation:

import datetime
import glob
import os
import re

def change_timestamps(source_folder, hourdiff = -1):

    file_re = re.compile(r'(.*)_(\d{8}-\d{6})\.jpg')
    for source_file_name in glob.iglob(os.path.join(source_folder, '*.jpg')):
        file_match = file_re.match(source_file_name)
        if file_match is not None:
            old_time = datetime.datetime.strptime(file_match.group(2), "%Y%m%d-%H%M%S")
            new_time = old_time + datetime.timedelta(hours = hourdiff)
            new_file_str = '{}_{}.jpg'.format(file_match.group(1), new_time.strftime("%Y%m%d-%H%M%S"))
            new_file_name = os.path.join(source_folder, new_file_str)
            os.replace(source_file_name, new_file_name)
Billy
  • 5,179
  • 2
  • 27
  • 53