目录
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/dir3
3.2 使用详细模式
启用详细模式:
python folder_size_improved.py -v
或
python folder_size_improved.py --verbose
这将显示每个目录的具体大小。