随笔 - 22  文章 - 0 评论 - 0 阅读 - 76
< 2025年2月 >
26 27 28 29 30 31 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 1
2 3 4 5 6 7 8

也许你曾经经历过查找一个文件夹,里面有几十个、几百个,甚至上千个文件,需要手工进行复制、改名、移动或压缩。或者考虑下面这样的任务:

  • 在一个文件夹及其所有子文件夹中,复制所有的 pdf 文件(且只复制 pdf 文件)
  • 针对一个文件夹中的所有文件,删除文件名中前导的零,该文件夹中有数百个文件,名为 spam001.txt、spam002.txt、spam003.txt 等。
  • 将几个文件夹的内容压缩到一个 ZIP 文件中(这可能是一个简单的备份系统)
  • 所有这种无聊的任务,正是在请求用 Python 实现自动化。通过对电脑编程来完成这些任务,你就把它变成了一个快速工作的文件职员,而且从不犯错。

1.shutil模块

shutil(或称为 shell 工具)模块中包含一些函数,让你在 Python 程序中复制、
移动、改名和删除文件。要使用 shutil 的函数,首先需要 import shutil。

1.1复制文件和文件夹

import  shutil,os
#复制文件
shutil.copy('D:\\学习成长\\python.txt','D:\\学习成长\\python')
#复制文件夹
shutil.copytree('D:\\学习成长\\python','D:\\学习成长\\python_copy')
#删除文件
os.remove('D:\\学习成长\\python\\python.txt')
#删除文件夹
shutil.rmtree('D:\\学习成长\\python_copy')

1.2移动和重命名文件和文件夹

import shutil
import os
#先创建一个文件夹
os.makedirs('D:\\学习成长\\python_20250224\\',exist_ok=True)
#移动文件
shutil.move('D:\\学习成长\\python.txt','D:\\学习成长\\python_20250224\\')
#重命名文件
os.rename('D:\\学习成长\\python_20250224\\python.txt','D:\\学习成长\\python_20250224\\python_20250224_lzd.txt')

1.3删除文件和文件夹

  • 用 os.unlink(path)将删除 path 处的文件。
  • 调用 os.rmdir(path)将删除 path 处的文件夹。该文件夹必须为空,其中没有任何文件和文件夹。
  • 调用 shutil.rmtree(path)将删除 path 处的文件夹,它包含的所有文件和文件夹都会被删除。
import shutil
#删除文件
os.unlink(r'D:\学习成长\python_20250224\regex\regex.txt')
# 删除文件
shutil.rmtree('D:\\学习成长\\python_20250224\\')

注意:使用unlink() 和 rmtree() 时一定要小心,因为删除文件和文件夹的操作无法撤销。

1.4压缩文件和文件夹

import shutil
#压缩文件
shutil.make_archive('D:\\学习成长\\python1','zip','D:\\学习成长\\python_20250224')

1.5解压缩文件和文件夹

import shutil
# 压缩文件路径
zip_file_path = r'D:\学习成长\python1.zip'

# 解压目标目录路径
extract_dir = r'D:\学习成长\extracted_files'

# 使用 unpack_archive 函数进行解压缩
shutil.unpack_archive(zip_file_path, extract_dir)

print(f'文件 {zip_file_path} 已成功解压到 {extract_dir}')

1.5 用 send2trash 模块安全地删除

send2trash 模块可以将文件和文件夹删除到回收站,而不会永久删除。使用 send2trash 模块比使用 os.unlink()、os.remove()、os.rmdir() 或 shutil.rmtree() 更安全。

import send2trash
send2trash.send2trash('D:\\学习成长\\python_copy')

注意:swnd2trash 不会释放磁盘空间只会将文件发送到垃圾箱

2.遍历目录树

import os
# 遍历目录树
# 使用os模块的walk函数遍历指定目录及其子目录
for folderName, subfolders, filenames in os.walk('D:\\学习成长\\python_20250224\\'):
    # 打印当前遍历到的文件夹名称
    print('The current folder is ' + folderName)
    # 遍历当前文件夹下的所有子文件夹
    for subfolder in subfolders:
        # 打印子文件夹的名称,并指出其属于哪个文件夹
        print('SUBFOLDER OF ' + folderName + ': ' + subfolder)
    # 遍历当前文件夹下的所有文件
    for filename in filenames:
        # 打印文件的名称,并指出其位于哪个文件夹内
        print('FILE INSIDE ' + folderName + ': '+ filename)

3.用os.walk()复制目录树

import os,shutil  # 导入os和shutil模块,os用于文件和目录操作,shutil用于文件复制等操作
def copytree(src,dst):  # 定义一个函数copytree,用于复制目录树
    # 复制目录树
    names = os.listdir(src)  # 获取源目录src中的所有文件和目录名,返回一个列表
    os.makedirs(dst,exist_ok=True)  # 创建目标目录dst,如果目录已存在则不会报错(exist_ok=True)
    for name in names:  # 遍历源目录中的所有文件和目录
        srcname = os.path.join(src,name)  # 构建源文件或目录的完整路径
        dstname = os.path.join(dst,name)  # 构建目标文件或目录的完整路径
        if os.path.isdir(srcname):  # 如果当前项是目录
            copytree(srcname,dstname)  # 递归调用copytree函数,复制子目录
        else:
            shutil.copy2(srcname,dstname)  # 使用shutil.copy2复制文件,保留文件的元数据
copytree('D:\\学习成长\\python_20250224\\','D:\\学习成长\\python_20250224_copy\\')  # 调用copytree函数,复制指定目录及其内容

递归复制文件夹是指通过编写递归函数来遍历源文件夹中的所有文件和子文件夹,并将它们复制到目标位置。这种方法提供了更大的灵活性,因为你可以在复制过程中进行各种自定义操作,例如过滤特定文件、修改文件内容等。

4.用glob模块获取文件名

glob 模块包含一个函数,用于查找符合特定规则的文件路径名,它支持通配符操作。

import glob
# 使用glob模块的glob函数查找所有以.txt结尾的文件
txt_files = glob.glob('D:\\学习成长\\python_20250224\\*.txt')
# 打印找到的文件列表
print(txt_files)

5.用正则表达式查找文件

import os,re
# 使用os模块的walk函数遍历指定目录及其子目录
for folderName, subfolders, filenames in os.walk('D:\\学习成长\\python_20250224\\'):
    # 打印当前遍历到的文件夹名称
    print('The current folder is ' + folderName)
    # 遍历当前文件夹下的所有子文件夹
    for subfolder in subfolders:
        # 打印子文件夹的名称,并指出其属于哪个文件夹
        print('SUBFOLDER OF ' + folderName + ': ' + subfolder)
    # 遍历当前文件夹下的所有文件
    for filename in filenames:
        # 打印文件的名称,并指出其位于哪个文件夹内
        print('FILE INSIDE ' + folderName + ': '+ filename)
        # 使用正则表达式匹配文件名
        if re.search(r'\d{4}-\d{2}-\d{2}', filename):
            print(f'Found a file with date in name: {filename}')

正则表达式还是要多用才能记得住

6.用zipfile模块压缩文件

import zipfile
# 创建一个ZipFile对象,用于读取和写入zip文件
with zipfile.ZipFile('D:\\学习成长\\python_20250224.zip', 'w') as myzip:
    # 将指定目录下的所有文件添加到zip文件中
    myzip.write('D:\\学习成长\\python_20250224')

7.用zipfile模块解压缩文件

import zipfile
# 创建一个ZipFile对象,用于读取和写入zip文件
with zipfile.ZipFile('D:\\学习成长\\python_20250224.zip', 'r') as myzip:
    # 将zip文件中的所有文件解压缩到指定目录
    myzip.extractall('D:\\学习成长\\python_20250224_extracted')

8项目1 将带有美国风格日期的文件改名为欧洲风格日期

import os,re
# 使用os模块的walk函数遍历指定目录及其子目录
for folderName, subfolders, filenames in os.walk('D:\\学习成长\\python_20250224\\'):
    # 遍历当前文件夹下的所有文件
    for filename in filenames:
        # 使用正则表达式匹配文件名
        if re.search(r'\d{4}-\d{2}-\d{2}', filename):
            # 获取文件名和扩展名
            name, ext = os.path.splitext(filename)
            # 将美国风格的日期转换为欧洲风格的日期
            new_name = re.sub(r'(\d{4})-(\d{2})-(\d{2})', r'\3.\2.\1', name)
            # 构建新的文件名和路径
            new_filename = new_name + ext
            new_filepath = os.path.join(folderName, new_filename)
            # 重命名文件
            os.rename(os.path.join(folderName, filename), new_filepath)
            print(f'Renamed {filename} to {new_filename}')

9项目2:将一个文件夹备份到一个 ZIP 文件中

import zipfile, os
import logging

def backupToZip(folder):
    folder = os.path.abspath(folder)  # make sure folder is absolute

    number = 1
    while True:
        zipFilename = os.path.basename(folder) + '_' + str(number) + '.zip'
        if not os.path.exists(zipFilename):
            break
        number = number + 1

    logging.info('Creating %s...' % (zipFilename))
    try:
        backupZip = zipfile.ZipFile(zipFilename, 'w')
        for foldername, subfolders, filenames in os.walk(folder):
            backupZip.write(foldername)
            for filename in filenames:
                filePath = os.path.join(foldername, filename)
                backupZip.write(filePath, os.path.join(os.path.basename(folder), os.path.relpath(filePath, folder)))
        backupZip.close()
    except Exception as e:
        logging.error(f"Error occurred while creating {zipFilename}: {e}")

# 配置日志记录
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')

# 指定要遍历的根目录
root_folder = 'D:\\学习成长\\python_20250224\\'
backupToZip(root_folder)

这个项目需要重写一下

10项目3:查找文件中的日期

import os,re
# 使用os模块的walk函数遍历指定目录及其子目录
for folderName, subfolders, filenames in os.walk('D:\\学习成长\\python_20250224\\'):
    # 遍历当前文件夹下的所有文件
    for filename in filenames:
        # 使用正则表达式匹配文件名
        if re.search(r'\d{4}-\d{2}-\d{2}', filename):
            print(f'Found a file with date in name: {filename}')

11项目4:将文件名中的日期转换为时间戳

import os,re,time
# 使用os模块的walk函数遍历指定目录及其子目录
for folderName, subfolders, filenames in os.walk('D:\\学习成长\\python_20250224\\'):
    # 遍历当前文件夹下的所有文件
    for filename in filenames:
        # 使用正则表达式匹配文件名
        if re.search(r'\d{4}-\d{2}-\d{2}', filename):
            # 获取文件名和扩展名
            name, ext = os.path.splitext(filename)
            # 将美国风格的日期转换为欧洲风格的日期
            new_name = re.sub(r'(\d{4})-(\d{2})-(\d{2})', r'\3.\2.\1', name)
            # 构建新的文件名和路径
            new_filename = new_name + ext
            new_filepath = os.path.join(folderName, new_filename)
            # 重命名文件
            os.rename(os.path.join(folderName, filename), new_filepath)
            print(f'Renamed {filename} to {new_filename}')

12项目5:查找文件中的电话号码

import os,re
# 使用os模块的walk函数遍历指定目录及其子目录
for folderName, subfolders, filenames in os.walk('D:\\学习成长\\python_20250224\\'):
    # 遍历当前文件夹下的所有文件
    for filename in filenames:
        # 使用正则表达式匹配文件名
        if re.search(r'\d{3}-\d{3}-\d{4}', filename):
            print(f'Found a file with phone number in name: {filename}')

13.小结

即使你是一个有经验的计算机用户,可能也会用鼠标和键盘手工处理文件。现在的文件浏览器使得处理少量文件的工作很容易。但有时候,如果用计算机的浏览器,你需要完成的任务可能要花几个小时。os 和 shutil 模块提供了一些函数,用于复制、移动、改名和删除文件。在删除文件时,你可能希望使用 send2trash 模块,将文件移动到回收站或垃圾箱,而不是
永久地删除它们。在编程处理文件时,最好是先注释掉实际会复制/移动/改名/删除文件的代码,添加 print()调用,这样你就可以运行该程序,验证它实际会做什么。通常,你不仅需要对一个文件夹中的文件执行这些操作,而是对所有下级子文件夹执行操作。os.walk()函数将处理这个艰苦工作,遍历文件夹,这样你就可以专
注于程序需要对其中的文件做什么。zipfile 模块提供了一种方法,用 Python 压缩和解压 ZIP 归档文件。和 os 和 shutil模块中的文件处理函数一起使用,很容易将硬盘上任意位置的一些文件打包。和许多独立的文件相比,这些 ZIP 文件更容易上传到网站,或作为 E-mail 附件发送。本书前面几章提供了源代码让你拷贝。但如果你编写自己的程序,可能在第一次编写时不会完美无缺。下一章将聚焦于一些 Python 模块,它们帮助你分析和调试程序,这样就能让程序很快正确运行。

14.练习

  • 1 shutil.copy()和 shutil.copytree()之间的区别是什么?
    shutil.copy() 函数将拷贝一个文件,而 shutil.copytree() 将拷贝整个文件夹,以及它的所有内容。
  • 2.什么函数用于文件移动?
    shutil.move() 函数用于重命名文件,以及文件移动。
  • 3.什么函数用于文件改名?
    os.rename() shutil.move() 函数用于重命名文件,以及文件移动。
  • 3.send2trash 和 shutil 模块中的删除函数之间的区别是什么?
    发送到回收站和永久删除
  • 4.ZipFile 对象有一个 close()方法,就像 File 对象的 close()方法。ZipFile 对象的什么方法等价于 File 对象的 open()方法?
    zipfile.ZipFile() 函数等价于 open() 函数,第一个参数是文件名,第二个参数是打开 ZIP 文件的模式(读、写或添加)。

15

编写一个程序,遍历一个目录树,查找特定扩展名的文件(诸如.pdf 或.jpg)。将它们复制到一个新文件夹中。

import os, shutil

def copy_files_with_extension(src_folder, dest_folder, extension):
    # 创建目标文件夹(如果不存在)
    if not os.path.exists(dest_folder):
        os.makedirs(dest_folder)

    # 遍历源文件夹及其子文件夹
    for root, dirs, files in os.walk(src_folder):
        for file in files:
            # 检查文件扩展名
            if file.endswith(extension):
                # 构建源文件路径和目标文件路径
                src_file = os.path.join(root, file)
                dest_file = os.path.join(dest_folder, file)

                # 复制文件
                shutil.copy2(src_file, dest_file)
                print(f'Copied {src_file} to {dest_file}')

# 示例用法
src_folder = 'D:\\学习成长\\python_20250224\\'
dest_folder = 'D:\\学习成长\\python_20250224\\pdf_files'
extension = '.pdf'

copy_files_with_extension(src_folder, dest_folder, extension)

16

编写一个程序,接受一个文件夹路径作为参数。该程序应该计算该文件夹中所有文件的总大小(以字节为单位),并打印结果。

import os

def calculate_total_size(folder_path):
    total_size = 0

    # 遍历文件夹及其子文件夹
    for root, dirs, files in os.walk(folder_path):
        for file in files:
posted on   Martinl_it  阅读(0)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 没有源码,如何修改代码逻辑?
· PowerShell开发游戏 · 打蜜蜂
· 在鹅厂做java开发是什么体验
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
点击右上角即可分享
微信分享提示