目录
1.Python 代码实现
2.Python 代码解释(部分)
1. 模块导入
2. ANSI 颜色编码
3. format_size 函数
4.get_directory_size 函数
5. scan_directory 函数
6. display_progress 函数
7. main 函数
3.运行脚本
3.1 基本用法
3.2 使用详细模式
1.Python 代码实现
#!/usr/bin/env python3
"""
Script Name   : folder_size_improved.py
# Author        : XinFan
# Created       : 21 January 2025
# Version       : 1.0.1Description:This script scans the specified directory (or current directory if none provided)and all its subdirectories to calculate and display the total size in a human-readable format.It includes additional features such as progress display, optional verbose mode, and support formultiple directory inputs.Usage:python folder_size_improved.py [directory1] [directory2] ... [-v | --verbose]
"""import os
import sys
import argparse
import threading
import time
from pathlib import Path# ANSI escape codes for colored output
GREEN = "\033[92m"
RED = "\033[91m"
YELLOW = "\033[93m"
ENDC = "\033[0m"def format_size(size):"""Convert size in bytes to a human-readable format."""for unit in ["Bytes", "KB", "MB", "GB", "TB"]:if size < 1024:return f"{size:.2f} {unit}"size /= 1024return f"{size:.2f} PB"def get_directory_size(directory):"""Recursively calculate the size of the given directory."""total_size = 0for entry in os.scandir(directory):if entry.is_file():try:total_size += entry.stat().st_sizeexcept FileNotFoundError:# Handle cases where file is deleted during scanpasselif entry.is_dir():total_size += get_directory_size(entry.path)return total_sizedef scan_directory(directory, progress, lock):"""Scan the directory and update the progress."""size = get_directory_size(directory)with lock:progress[directory] = sizedef display_progress(progress, lock, total_dirs):"""Display progress of the scanning process."""while True:with lock:completed = sum(1 for size in progress.values() if size is not None)if completed >= total_dirs:breakprint(f"\rScanning directories: {completed}/{total_dirs}", end="")time.sleep(1)print()  # Move to next line after scanning is completedef main():# Set up argument parsingparser = argparse.ArgumentParser(description="Calculate the size of specified directories.")parser.add_argument('directories', nargs='*', default=[os.getcwd()],help='Directories to scan. Defaults to current directory if none provided.')parser.add_argument('-v', '--verbose', action='store_true',help='Enable verbose output.')args = parser.parse_args()directories = args.directoriesverbose = args.verboseif verbose:print(f"Scanning directories: {', '.join(directories)}")progress = {}lock = threading.Lock()threads = []total_dirs = len(directories)# Start progress display threadprogress_thread = threading.Thread(target=display_progress, args=(progress, lock, total_dirs))progress_thread.start()# Start scanning threadsfor directory in directories:if os.path.isdir(directory):thread = threading.Thread(target=scan_directory, args=(directory, progress, lock))thread.start()threads.append(thread)else:print(f"{RED}Error:{ENDC} '{directory}' is not a valid directory.")total_dirs -= 1  # Decrement total_dirs since this is not a valid directory# Wait for all scanning threads to finishfor thread in threads:thread.join()# Signal progress thread to finishwith lock:progress['__DONE__'] = Trueprogress_thread.join()# Calculate total sizetotal_size = sum(progress.values())# Display resultsprint(f"\n{GREEN}Total Size:{ENDC} {format_size(total_size)}")if verbose:for directory in directories:size = progress.get(directory, 0)print(f"  {directory}: {format_size(size)}")if __name__ == "__main__":main()2.Python 代码解释(部分)
1. 模块导入
import os
import sys
import argparse
import threading
import time
from pathlib import Path- os:提供与操作系统交互的功能,特别是文件和目录操作。
- sys:提供对解释器使用的一些变量和函数的访问,特别是用于获取命令行参数。
- argparse:用于解析命令行参数,提供更强大的参数解析功能。
- threading:用于创建和管理线程,实现并发处理。
- time:提供时间相关的函数,例如 sleep。
- pathlib.Path:提供面向对象的路径操作方式,简化路径处理。
2. ANSI 颜色编码
GREEN = "\033[92m"
RED = "\033[91m"
YELLOW = "\033[93m"
ENDC = "\033[0m"- 说明:定义 ANSI 转义码,用于在终端中输出彩色文本。 - GREEN:绿色文本。
- RED:红色文本。
- YELLOW:黄色文本。
- ENDC:重置文本颜色。
 
3. format_size 函数 
 
def format_size(size):"""Convert size in bytes to a human-readable format."""for unit in ["Bytes", "KB", "MB", "GB", "TB"]:if size < 1024:return f"{size:.2f} {unit}"size /= 1024return f"{size:.2f} PB"- 说明:将字节数转换为更易读的格式,例如 KB, MB, GB 等。
- 参数: - size:文件或目录的大小,以字节为单位。
 
- 返回值:格式化后的字符串,例如 "1500.00 Bytes","1.46 KB","0.00 GB"。
- 逻辑: - 遍历单位列表,从 Bytes 到 TB。
- 如果当前大小小于 1024,则返回格式化后的字符串。
- 否则,将大小除以 1024,继续检查下一个单位。
 
4.get_directory_size 函数 
 
def get_directory_size(directory):"""Recursively calculate the size of the given directory."""total_size = 0for entry in os.scandir(directory):if entry.is_file():try:total_size += entry.stat().st_sizeexcept FileNotFoundError:# Handle cases where file is deleted during scanpasselif entry.is_dir():total_size += get_directory_size(entry.path)return total_size- 说明:递归计算指定目录及其所有子目录的总大小。
- 参数: - directory:要扫描的目录路径。
 
- 返回值:总大小,以字节为单位。
- 逻辑: - 使用 os.scandir遍历目录内容。
- 如果是文件,尝试获取文件大小并累加到 total_size。- 如果文件在扫描过程中被删除,捕捉 FileNotFoundError异常并跳过。
 
- 如果文件在扫描过程中被删除,捕捉 
- 如果是子目录,递归调用 get_directory_size并累加其大小。
 
- 使用 
5. scan_directory 函数 
 
def scan_directory(directory, progress, lock):"""Scan the directory and update the progress."""size = get_directory_size(directory)with lock:progress[directory] = size- 说明:扫描指定目录并更新进度。
- 参数: - directory:要扫描的目录路径。
- progress:一个字典,用于存储每个目录的大小。
- lock:一个线程锁,用于同步对 progress的访问。
 
- 逻辑: - 调用 get_directory_size计算目录大小。
- 使用 lock确保对progress的线程安全更新。
 
- 调用 
6. display_progress 函数 
 
def display_progress(progress, lock, total_dirs):"""Display progress of the scanning process."""while True:with lock:completed = sum(1 for size in progress.values() if size is not None)if completed >= total_dirs:breakprint(f"\rScanning directories: {completed}/{total_dirs}", end="")time.sleep(1)print()  # Move to next line after scanning is complete- 说明:在终端中显示扫描进度。
- 参数: - progress:一个字典,存储每个目录的大小。
- lock:一个线程锁,用于同步对 progress的访问。
- total_dirs:要扫描的目录总数。
 
- 逻辑: - 进入一个无限循环,每秒更新一次进度。
- 使用 lock获取当前完成的目录数量。
- 如果完成的目录数量达到 total_dirs,则退出循环。
- 使用 \r回到行首,覆盖之前的输出。
- 显示当前扫描进度,例如 "Scanning directories: 5/10"。
- 休眠 1 秒。
 
7. main 函数
 
def main():# Set up argument parsingparser = argparse.ArgumentParser(description="Calculate the size of specified directories.")parser.add_argument('directories', nargs='*', default=[os.getcwd()],help='Directories to scan. Defaults to current directory if none provided.')parser.add_argument('-v', '--verbose', action='store_true',help='Enable verbose output.')args = parser.parse_args()directories = args.directoriesverbose = args.verboseif verbose:print(f"Scanning directories: {', '.join(directories)}")progress = {}lock = threading.Lock()threads = []total_dirs = len(directories)- 说明:主函数,设置命令行参数解析并初始化扫描过程。
- 逻辑: - 使用 argparse设置命令行参数:- directories:位置参数,指定要扫描的目录。默认为当前工作目录。
- -v, --verbose:可选参数,启用详细输出。
 
- 获取用户输入的目录列表和详细模式标志。
- 如果启用详细模式,打印要扫描的目录列表。
- 初始化 progress字典,用于存储每个目录的大小。
- 初始化线程锁 lock。
- 初始化线程列表 threads。
- 获取要扫描的目录总数 total_dirs。
 
- 使用 
3.运行脚本
打开终端或命令提示符,导航到脚本所在的目录,然后运行以下命令:
python folder_size_improved.py [options] [directories]3.1 基本用法
-  扫描当前目录: python folder_size_improved.py
这将扫描当前工作目录及其所有子目录,并显示总大小。
- 扫描指定目录:         python folder_size_improved.py /path/to/directory
这将扫描指定的目录及其所有子目录。
- 扫描多个目录:
python folder_size_improved.py /path/to/dir1 /path/to/dir2 /path/to/dir33.2 使用详细模式
启用详细模式:
python folder_size_improved.py -v
或
python folder_size_improved.py --verbose
这将显示每个目录的具体大小。