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.
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.
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.
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.
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?
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.
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.
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.
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.
Practice the Trace
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
- A hierarchical backup path uses a main directory, a date-based subdirectory, and a time-stamped zip file.
- time.strftime('%Y%m%d') supplies the date directory name, while time.strftime('%H%M%S') supplies the time-based archive name.
- os.path.exists checks whether the date directory is already present.
- os.mkdir creates the date directory only when the check shows that it is absent.
- 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.