Concepts / Using Python's os Module for File Operations

Using Python's os Module for File Operations

Hierarchical file-naming organizes backups into a main directory containing date-based subdirectories, each containing time-stamped zip files, making backups easier to manage and verify.

  • Programming

From Clutter to Structure

A backup script can work correctly and still become difficult to use. If every archive is stored in one directory with a long timestamped filename, repeated backups can produce dozens of similarly named files. A hierarchical naming scheme improves this situation by dividing the backups first by date and then by time.

The organization has three levels: a main backup directory, a date-based subdirectory, and a time-stamped zip file inside that subdirectory.

The Three-Level Backup Path

The main directory is the common home for all backups. Each date-based subdirectory groups backups made on one day. Each zip file inside that date directory represents a backup made at a particular time. This makes it easier to navigate to a day and then distinguish the backups created during that day.

containscontainsbackupmain directory20240115date directory143022.ziptime-stamped archive
What contains what, and how does a backup path organize files by date and time?

Reading a Backup Path

Interpret the path /Users/swa/backup/20240115/143022.zip.

Main directory: backup is the main directory that contains the organized backups.

Date directory: 20240115 is the date-based directory. The source uses this form for January 15, 2024.

Time-stamped file: 143022.zip is the zip archive named with the time 14:30:22.

The path identifies a backup made on January 15, 2024, at 2:30:22 PM.

Turning Time into Names

The time.strftime function returns a formatted string representing the current date or time. In this backup design, one format produces the date directory name and another produces the zip filename. The format code %Y%m%d produces a year-month-day string such as 20240115, while %H%M%S produces a 24-hour time string such as 143022.

format datereturnsformat timereturnsCurrent date andtime%Y%m%ddate string20240115folder name%H%M%Stime string143022.ziparchive name
How does the current date and time become the folder name and timestamped file name?
python

Checking Before Creating

Before saving an archive into the date-based directory, the script must determine whether that directory already exists. os.path.exists performs the check. If the directory exists, the script can use it. If it does not exist, os.mkdir creates it. This check matters when the script runs repeatedly, because a second backup on the same day should use the existing date directory rather than attempt to create it again.

inspectyesnocontinuecontinueDate directory20240115os.path.existscheck directoryUse directoryalready existsArchive pathready for zip fileos.mkdircreate directory
What happens next when the date-based directory already exists versus when it does not?

import os import time backup_dir = '/Users/swa/backup' date_name = time.strftime('%Y%m%d') date_dir = backup_dir + '/' + date_name if not os.path.exists(date_dir): os.mkdir(date_dir)

What do you think happens?

If the script runs again on the same day after the date directory has already been created, which branch should run?

  • The existing-directory branch
  • The os.mkdir branch
Reveal answer

Answer: The existing-directory branch

os.path.exists reports that the date directory is already present, so os.mkdir is not needed for that run.

Building the Archive Command

After the directory and names are ready, the script constructs a system command for creating the compressed archive. The command contains the target zip path and the source paths to be archived. The resulting command is passed to os.system, which executes it as an operating-system command.

add sourcesadd destinationpass stringcreateSource pathsfiles or directorieszip -r commandconstructed stringos.systemexecute commandZip archivecreated backupTarget zip pathdate and time name
How do source files and a destination path become a command that creates a zip archive?
python

os.system executes the supplied shell command and returns 0 when the command succeeds. A non-zero return value indicates failure, so the script can use the result to verify whether the backup completed.

Tracing a Second Backup

Imagine that the script runs on January 15, 2024, at 2:30:22 PM and then runs again on the same day at 6:05:00 PM. The date string remains the same, so both backups belong in the 20240115 directory. The time string changes, so the second backup receives a different time-stamped zip filename.

containscontainscontains20240115date directory143022.zipfirst archive20240115same date directory143022.zipexisting archive180500.zipsecond archive
What changes when the backup runs again on the same date at a different time?

Following the Second Run

Determine what happens when the backup runs on January 15, 2024, at 18:05:00 after a backup has already run earlier that day.

Format the date: The %Y%m%d format produces 20240115 again.

Check the directory: The 20240115 directory already exists because an earlier backup used it.

Format the time: The %H%M%S format produces 180500 for 18:05:00.

Create the new target: The new archive is placed inside the existing date directory with the name 180500.zip.

The second run reuses 20240115 and adds another time-stamped archive inside it.

prepare date pathcreate when absentdirectory readyruntime.strftimedate and time stringsos.path.existscheck date directoryos.mkdironly if neededzip commandtarget and sourcesos.systemarchive operation
What is the sequence from preparing the directory and names to creating the final backup archive?

Mistakes Beginners Make

  • Creating the date directory every time

    A repeated run on the same day may encounter a directory that was already created by an earlier run.

    Fix: Use os.path.exists first and call os.mkdir only when the directory is absent.

  • Putting the full timestamp into one flat filename

    Repeated backups can make the directory cluttered with similarly named files, making a particular day harder to find.

    Fix: Use the date portion for a subdirectory and the time portion for the zip filename.

  • Ignoring the result from os.system

    The script loses the supplied success or failure signal for the archive operation.

    Fix: Check whether the returned value is 0 for success or non-zero for failure.

  • Mixing up the date and time formats

    The intended hierarchy uses the date to group backups and the time to distinguish archives within that group.

    Fix: Use %Y%m%d for the date directory and %H%M%S for the zip filename.

Practical Design Notes

Treat the backup path as a sequence of decisions rather than as one long filename. First produce the date and time strings. Next prepare the date directory by checking and, when necessary, creating it. Then form the target zip path, construct the command with the source paths, execute it with os.system, and inspect the return value.

python

Practice the Trace

EASY

Suppose the main backup directory is backup, the date string is 20240115, the time string is 180500, and the source is notes. Describe the date directory, the target zip filename, and the order of operations the script should follow.

Hints
  • The date string names the subdirectory.
  • The time string names the zip file.
  • Remember to check for the date directory before creating it.
  • The final command uses the target path and the source path.

Practice Solution

Use the supplied names to describe the resulting backup organization.

Build the date directory: Combine backup and 20240115 to identify the date-based directory backup/20240115.

Build the archive name: Add the time string and the zip extension to obtain 180500.zip.

Check the directory: Use os.path.exists on the date directory. Call os.mkdir only if it is absent.

Construct the command: Use the target archive path and notes as the inputs to the zip command, then pass the command to os.system.

The target archive is backup/20240115/180500.zip, and the directory check happens before the archive command runs.

Key Takeaways

  1. A hierarchical backup path uses a main directory, a date-based subdirectory, and a time-stamped zip file.
  2. time.strftime('%Y%m%d') supplies the date directory name, while time.strftime('%H%M%S') supplies the time-based archive name.
  3. os.path.exists checks whether the date directory is already present.
  4. os.mkdir creates the date directory only when the check shows that it is absent.
  5. os.system runs the zip command, and its return value is 0 for success and non-zero for failure.

Key Takeaways

  • Hierarchical file naming makes repeated backups easier to locate and verify.
  • Date strings organize backups into subdirectories, while time strings distinguish archives made on the same day.
  • Checking with os.path.exists before calling os.mkdir allows the script to handle repeated runs.
  • The final zip command combines a destination path with source paths and runs through os.system.
  • The return value from os.system gives the script a way to identify success or failure.