title: Manipulate files and directories description: Python's os module provides the function of detecting the operating system type:

Manipulate files and directories

When writing Python scripts across platforms, the most common pitfalls are hard-coded path separators, adaptation system commands, or simply not knowing which operating system the current code is running on. At this time,osfamily (includingos.path)、shutil, and Python 3.4 is super easy to use.pathlib, is your savior!

This article will take you through the core tool chain for file and directory operations in Python, and give you a bunch of security tips and practical cases, so that the scripts you write are clear and reliable, and can run smoothly on Windows / Linux / macOS.


Operating system type detection

You must first understand the running environment of the script before you can make targeted adaptations - such as path processing, calling system commands, etc.

import os

# 获取最基础的系统标识
print(os.name)  # 输出结果只有两种

💡 System corresponding to common logos:

  • posix:Linux, macOS, BSD and other Unix-like systems
  • nt:Windows system

If you need to obtain more detailed kernel, host name and other information (only supports Unix-like systems), you can do this:

if os.name == 'posix':
    print(os.uname())
    # 输出示例:posix.uname_result(sysname='Linux', nodename='ubuntu-server', 
    #                        release='6.5.0', version='#1 SMP PREEMPT_DYNAMIC', machine='x86_64')

⚠️ Note: Call directly on Windowsos.uname()An error will be reported, so you must judge first.os.name


Environment variable operations

All system environment variables are stored in dictionary-like structuresos.environinside. Although it can be assigned directly, it is highly recommended to use.get()Method ** to avoid throwing because the variable does not existKeyError

# ⚠️ 生产环境中不要随便打印所有环境变量,可能会泄露敏感信息!
# print(os.environ)

# 获取已知变量(推荐)
python_path = os.environ.get('PYTHONPATH')

# 获取不存在的变量,并指定默认值
default_config = os.environ.get('APP_CONFIG_PATH', '/etc/app/default.conf')

Writing this way is not only safer, but also allows you to provide fallback solutions elegantly.


File and directory operations

Core Principles💡

Never manually concatenate path strings (e.g.'/Users/xxx' + 'test.txt')。
Different systems have different delimiters - Windows uses\, for Unix-like/. Manual splicing breaks cross-platform compatibility and causes scripts to crash silently.

Here are two path tools: classic but highly compatibleos.path, as well as more modern and elegantpathlib


Classic path tool: os.path

Although it is now more recommendedpathlib,butos.pathIt has the best compatibility (common to Python 2.x/3.x) and is still used by many old projects. It is still necessary to master it:

# 1. 获取绝对路径
current_dir = os.path.abspath('.')
print(current_dir)  # 输出类似 /home/xxx/Desktop 或 C:\Users\xxx\Desktop

# 2. 跨平台路径拼接(自动适配分隔符)
full_path = os.path.join('/Users/xxx', 'docs', 'python', 'intro.txt')
print(full_path)  # Unix-like: /Users/xxx/docs/python/intro.txt;Windows 自动变为反斜杠

# 3. 拆分路径(目录 + 文件名/目录名)
parent_dir, last_part = os.path.split('/Users/xxx/docs/intro.txt')
print(f"父目录:{parent_dir},最后部分:{last_part}")

# 4. 拆分文件名(主名 + 扩展名)
root_name, ext = os.path.splitext('intro.txt')
print(f"主名:{root_name},扩展名:{ext}")

# 5. 常见属性检查
print(os.path.exists('test.txt'))     # True/False
print(os.path.isfile('test.txt'))     # True/False
print(os.path.isdir('my_project'))    # True/False

Modern path tools: pathlib (preferred for Python 3.4+)

pathlibUse an object-oriented method to process paths and turn the paths into objects instead of strings. The code is simpler and more readable. It can be calledos.pathcomprehensive replacement.

from pathlib import Path

# 1. 初始化路径对象
p = Path('.')                        # 当前目录
full_p = Path('/Users/xxx/docs/python/intro.txt')

# 2. 路径操作(链式调用,一气呵成)
parent_dir = full_p.parent
last_part  = full_p.name
root_name  = full_p.stem
ext        = full_p.suffix

# 3. 跨平台拼接(用 / 操作符,超级直观!)
new_p = Path('/Users/xxx') / 'docs' / 'python' / 'intro.txt'

# 4. 常见属性检查
print(new_p.exists())
print(new_p.is_file())
print(new_p.is_dir())

# 5. 快速遍历
py_files = list(p.glob('*.py'))       # 当前目录下的所有 .py 文件
all_py_files = list(p.rglob('*.py'))  # 递归遍历所有子目录里的 .py 文件

For newbies,pathlibThe syntax is more like natural language, and it is recommended to use it directly in new Python projects.


Directory operations

Doesn't workosstillpathlib, the underlying logic is similar, but the syntax is different. Here the two methods are put together for easy comparison:

Use os module
# 1. 创建单级目录(已存在会报错)
os.mkdir('single_dir')

# 2. 创建多级目录(Python 3.2+ 推荐,加 exist_ok=True 已存在不报错)
os.makedirs('multi/level/dir', exist_ok=True)

# 3. 删除**空目录**(非空会报错)
os.rmdir('single_dir')

# 4. 列出目录下所有内容(不含子目录内容)
print(os.listdir('.'))
Use pathlib
p = Path('.')

# 1. 创建单级/多级目录(parents=True 自动创建父目录,exist_ok=True 已存在不报错)
(p / 'multi/level/dir').mkdir(parents=True, exist_ok=True)

# 2. 删除空目录
(p / 'single_dir').rmdir()

# 3. 列出目录下所有内容(返回 Path 对象列表,更方便后续操作)
print(list(p.iterdir()))

File operations

Use os module
# 1. 重命名/移动文件(也可移动目录,但空目录推荐用 rmdir)
os.rename('old.txt', 'new.txt')
os.rename('src_dir/file.txt', 'dst_dir/file.txt')

# 2. 删除文件(删除目录会报错)
os.remove('file_to_delete.txt')
Use pathlib
old_p = Path('old.txt')
new_p = Path('new.txt')

# 1. 重命名/移动文件
old_p.rename(new_p)

# 2. 移动时如果目标目录还不存在,可以先创建
# (new_p.parent).mkdir(parents=True, exist_ok=True)
# old_p.rename(new_p)

# 3. 删除文件(Python 3.8+ 加 missing_ok=True,不存在也不报错)
old_p.unlink(missing_ok=True)

Advanced file operations

os / pathlibIt can cover basic needs, but advanced operations such as copying files, recursively deleting, and moving large directories are best left toshutilModule (short for "shell utilities"). It encapsulates many efficient and safe file operations, which is much more reliable than manually implementing them yourself.

import shutil

# 1. 复制文件(推荐 copy2,保留修改时间、权限等元数据)
shutil.copy2('source.txt', 'destination.txt')
shutil.copy2('source.txt', 'backup_dir/')  # 复制到指定目录

# 2. 递归复制整个目录(目标目录不能已存在!)
shutil.copytree('src_project', 'dst_project_backup')

# 3. 递归删除目录(⚠️ 超级危险!没有回收站!操作前务必确认!)
# shutil.rmtree('dir_to_delete')

# 4. 移动文件/目录(自动判断是复制+删除还是直接移动)
shutil.move('src', 'dst')

Useshutil.rmtreeBe sure to make sure the variable name is correct beforehand. It is best to add a second confirmation to avoid deleting it by mistake.


Practical Tips

1. List all subdirectories under the current directory

# os.path 版本
subdirs = [d for d in os.listdir('.') if os.path.isdir(d)]

# pathlib 版本(更直观)
subdirs = [d for d in Path('.').iterdir() if d.is_dir()]

2. Search files recursively

For example, find out the file names in the current directory and all subdirectories containinglogFiles:

# os.walk 版本(Python 2.x/3.x 通用)
def find_logs(root='.'):
    for root_dir, _, files in os.walk(root):
        for f in files:
            if 'log' in f:
                print(os.path.relpath(os.path.join(root_dir, f)))

# pathlib 版本(更简洁)
def find_logs(root='.'):
    for log_file in Path(root).rglob('*log*'):
        if log_file.is_file():
            print(log_file.relative_to(root))

3. Calculate the total size of the directory

# os.walk 版本
def get_dir_size(root='.'):
    total = 0
    for dirpath, _, filenames in os.walk(root):
        for f in filenames:
            fp = os.path.join(dirpath, f)
            # 跳过可能已不存在的临时文件,避免 os.path.getsize 报错
            if os.path.isfile(fp):
                total += os.path.getsize(fp)
    return total

# 一个简单的大小格式化工具(可选)
def format_size(size):
    for unit in ['B', 'KB', 'MB', 'GB', 'TB']:
        if size < 1024.0:
            return f"{size:.2f} {unit}"
        size /= 1024.0

Summarize

  • Environment Detection: Useos.nameQuick judgment system, can be further used under Unix-likeos.uname()Get details.
  • Path Handling: Python 3.4+ preferredpathlib(Object-oriented, support/operator, chain call), used in old projects or when compatibility with Python 2 is requiredos.path
  • Basic Directory/File Operations: UseosorpathlibFor the corresponding methods, pay attention to cross-platform and exception-handling.
  • Complex operations: copy, recursive deletion, move, etc. are handed overshutil, powerful and secure package.
  • Safety Reminder:
  • Do not print easily in production environmentos.environall content.
  • Delete operations (especiallyrmtree) must be judged or confirmed twice before proceeding.
  • Try to use it before operation.exists().is_file().is_dir()Check status to avoid unnecessary exceptions.

Mastering this tool chain, you can write concise and robust cross-platform file operation logic, whether it is daily scripts or project code.