Fundamentals 17 min read

Python Path Handling: os.path, pathlib, glob, and shutil Overview

This article provides a comprehensive guide to Python's path manipulation tools, covering the os.path module functions, the object‑oriented pathlib API, file‑matching with glob, and advanced file operations using shutil, complete with code examples and usage recommendations.

Test Development Learning Exchange
Test Development Learning Exchange
Test Development Learning Exchange
Python Path Handling: os.path, pathlib, glob, and shutil Overview

Path manipulation is a common task in Python, and the language offers several built‑in libraries that simplify cross‑platform file and directory handling.

os.path provides basic functions for joining paths, checking existence, determining file or directory types, and extracting components. Common functions include os.path.join , os.path.exists , os.path.isdir , os.path.isfile , os.path.basename , os.path.dirname , os.path.split , os.path.splitext , os.path.abspath , and os.path.relpath .

import os
joined_path = os.path.join("folder", "subfolder", "file.txt")
print(joined_path)  # folder/subfolder/file.txt (Linux/macOS) or folder\subfolder\file.txt (Windows)
path_to_check = "/etc/passwd"
if os.path.exists(path_to_check):
    print(f"{path_to_check} exists")
else:
    print(f"{path_to_check} does not exist")
directory_path = "/usr/local/bin"
if os.path.isdir(directory_path):
    print(f"{directory_path} is a directory")
else:
    print(f"{directory_path} is not a directory")
file_path = "/etc/passwd"
if os.path.isfile(file_path):
    print(f"{file_path} is a file")
else:
    print(f"{file_path} is not a file")
full_path = "/home/user/documents/report.txt"
base_name = os.path.basename(full_path)
print(base_name)  # report.txt
dir_name = os.path.dirname(full_path)
print(dir_name)  # /home/user/documents
head, tail = os.path.split(full_path)
print(f"head: {head}, tail: {tail}")  # head: /home/user/documents, tail: report.txt
filename, extension = os.path.splitext(full_path)
print(f"filename: {filename}, extension: {extension}")  # filename: /home/user/documents/report, extension: .txt
relative_path = "documents/report.txt"
absolute_path = os.path.abspath(relative_path)
print(absolute_path)  # absolute path of the file
target_path = "/home/user/documents/report.txt"
start_path = "/home/user"
relative_path = os.path.relpath(target_path, start=start_path)
print(relative_path)  # documents/report.txt

pathlib offers an object‑oriented approach to file system paths, improving readability and maintainability. Key class Path provides methods such as exists() , is_dir() , is_file() , parent , name , suffix , with_name() , with_suffix() , iterdir() , mkdir() , unlink() , and resolve() .

from pathlib import Path
current_dir = Path('.')
print(current_dir)  # .
file_path = Path('/home/user/documents/report.txt')
print(file_path)   # /home/user/documents/report.txt
file_path = Path('/etc/passwd')
if file_path.exists():
    print(f"{file_path} exists")
else:
    print(f"{file_path} does not exist")
directory_path = Path('/usr/local/bin')
if directory_path.is_dir():
    print(f"{directory_path} is a directory")
file_path = Path('/etc/passwd')
if file_path.is_file():
    print(f"{file_path} is a file")
parent_directory = file_path.parent
print(parent_directory)  # /home/user/documents
file_name = file_path.name
print(file_name)  # report.txt
extension = file_path.suffix
print(extension)  # .txt
new_file_path = file_path.with_name('summary.txt')
print(new_file_path)  # /home/user/documents/summary.txt
new_file_path = file_path.with_suffix('.md')
print(new_file_path)  # /home/user/documents/report.md
for entry in Path('/home/user/documents').iterdir():
    print(entry)  # each file or subdirectory
new_directory = Path('./new_folder')
new_directory.mkdir(exist_ok=True)
file_to_delete = Path('./old_file.txt')
if file_to_delete.exists():
    file_to_delete.unlink()
relative_path = Path('documents/report.txt')
absolute_resolved_path = relative_path.resolve()
print(absolute_resolved_path)  # absolute resolved path

glob simplifies file searching with pattern matching. The primary functions are glob.glob (returns a list) and glob.iglob (returns an iterator). Wildcards such as * , ? , [seq] , and [!seq] are supported.

import glob
txt_files = glob.glob('*.txt')
print(txt_files)  # list of .txt files in current directory
py_files_recursive = glob.glob('src/**/*.py', recursive=True)
print(py_files_recursive)  # all .py files under src
for txt_file in glob.iglob('*.txt'):
    print(txt_file)
for py_file in glob.iglob('src/**/*.py', recursive=True):
    print(py_file)
csv_files = glob.glob('data*.csv')
print(csv_files)
ab_files = glob.glob('?a*.txt') + glob.glob('?b*.txt')
print(ab_files)
numbered_files = glob.glob('*[0-9]*')
print(numbered_files)
from pathlib import Path
import glob
absolute_txt_paths = [Path(p).resolve() for p in glob.glob('*.txt')]
print(absolute_txt_paths)
py_parent_dirs = set(Path(p).parent for p in glob.glob('**/*.py', recursive=True))
print(py_parent_dirs)
import glob, os
non_empty_txt_files = [f for f in glob.glob('*.txt') if os.path.getsize(f) > 0]
print(non_empty_txt_files)
import time
one_week_ago = time.time() - 7*24*60*60
recent_py_files = [f for f in glob.glob('**/*.py', recursive=True) if os.path.getmtime(f) > one_week_ago]
print(recent_py_files)

shutil focuses on higher‑level file operations such as copying, moving, and deleting files or entire directory trees, as well as creating archives and checking disk usage. Frequently used functions include shutil.copy , shutil.copytree , shutil.rmtree , shutil.move , shutil.make_archive , shutil.unpack_archive , and shutil.disk_usage .

import shutil, os
source_file = 'example.txt'
destination_file = 'backup/example.txt'
os.makedirs(os.path.dirname(destination_file), exist_ok=True)
shutil.copy(source_file, destination_file)
print(f"File copied to {destination_file}")
source_directory = 'my_project'
destination_directory = 'my_project_backup'
shutil.copytree(source_directory, destination_directory, dirs_exist_ok=True)
print(f"Directory tree copied to {destination_directory}")
directory_to_remove = 'my_project_backup'
if os.path.exists(directory_to_remove):
    shutil.rmtree(directory_to_remove)
    print(f"Directory {directory_to_remove} removed")
else:
    print(f"Directory {directory_to_remove} does not exist")
source_item = 'example.txt'
destination_item = 'moved_files/example.txt'
os.makedirs(os.path.dirname(destination_item), exist_ok=True)
shutil.move(source_item, destination_item)
print(f"Item moved to {destination_item}")
archive_name = 'my_project_backup'
shutil.make_archive(archive_name, 'zip', 'my_project')
print(f"Archive {archive_name}.zip created")
archive_file = 'my_project_backup.zip'
extract_directory = 'extracted_project'
shutil.unpack_archive(archive_file, extract_directory)
print(f"Archive extracted to {extract_directory}")
total, used, free = shutil.disk_usage('/')
print(f"Total: {total // (2**30)} GB")
print(f"Used: {used // (2**30)} GB")
print(f"Free: {free // (2**30)} GB")

Choose the appropriate library based on your needs: use os.path for simple tasks, pathlib for an object‑oriented approach, glob for pattern‑based file searching, and shutil for advanced file operations such as copying, moving, and archiving.

PythonFile Systemshutilglobos.pathPath Handlingpathlib
Test Development Learning Exchange
Written by

Test Development Learning Exchange

Test Development Learning Exchange

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.