本文目录导读:

是的,实用脚本完全可以实现批量归档功能,批量归档的核心逻辑就是遍历文件列表,然后对每个文件执行归档操作。
下面我为你提供几个不同场景下的实用脚本方案,涵盖常见的 zip 和 tar.gz 格式,并分别使用 Bash (Linux/macOS) 和 PowerShell (Windows) 实现。
按日期批量归档日志文件 (Bash)
场景:将 /var/log/myapp/ 目录下所有 .log 文件按当天日期打包成一个 tar.gz 文件,然后删除原文件以节省空间。
#!/bin/bash
# 配置
SOURCE_DIR="/var/log/myapp"
ARCHIVE_DIR="/backups/logs"
DATE=$(date +%Y%m%d)
ARCHIVE_NAME="logs_${DATE}.tar.gz"
# 创建归档目录
mkdir -p "$ARCHIVE_DIR"
# 查找所有 .log 文件并打包
echo "开始批量归档日志文件..."
tar -czf "${ARCHIVE_DIR}/${ARCHIVE_NAME}" -C "$SOURCE_DIR" --no-recursion *.log
# 检查打包是否成功
if [ $? -eq 0 ]; then
echo "归档成功:${ARCHIVE_DIR}/${ARCHIVE_NAME}"
# 删除原文件(可选,注释掉则保留)
# rm -f "${SOURCE_DIR}"/*.log
# echo "原始日志文件已删除。"
else
echo "归档失败!"
exit 1
fi
关键点:
tar -czf:创建 gzip 压缩的 tar 包。-C "$SOURCE_DIR":先进入源目录,确保打包的文件名不包含路径。--no-recursion:仅打包当前匹配的文件,不递归子目录。- 成功后可以执行
rm来清理原始文件。
按文件类型批量归档到多个压缩包 (Bash)
场景:将 ~/Documents/ 下所有 .pdf 文件打包成 pdfs.zip,所有 .jpg 和 .png 文件打包成 images.zip。
#!/bin/bash
SOURCE_DIR="$HOME/Documents"
OUTPUT_DIR="$HOME/Archives"
mkdir -p "$OUTPUT_DIR"
# 批量归档 PDF 文件
echo "归档 PDF 文件..."
zip -j "${OUTPUT_DIR}/pdfs.zip" "${SOURCE_DIR}"/*.pdf 2>/dev/null
if [ $? -eq 0 ]; then
echo " pdfs.zip 创建成功"
else
echo " 未找到 PDF 文件或归档失败"
fi
# 批量归档图片文件 (jpg 和 png)
echo "归档图片文件..."
# 使用 -r 递归查找子目录中的图片
zip -r "${OUTPUT_DIR}/images.zip" "${SOURCE_DIR}" -i "*.jpg" "*.png" 2>/dev/null
if [ $? -eq 0 ]; then
echo " images.zip 创建成功"
else
echo " 未找到图片文件或归档失败"
fi
echo "批量归档完成。"
关键点:
zip -j:-j参数表示移除文件路径,只存文件名(避免压缩包内出现完整路径)。zip -r -i:-r递归子目录,-i指定要包含的文件模式。2>/dev/null:将错误信息(如“未找到文件”)重定向到空设备,避免脚本输出难看。
根据文件名模式批量归档 (PowerShell)
场景:在 Windows 上,将 C:\Reports\ 下所有包含 2024 的 .xlsx 文件,按月份分成多个 zip 包(2024-01.zip, 2024-02.zip...)。
# 配置
$sourceDir = "C:\Reports"
$outputDir = "C:\ArchivedReports"
$pattern = "*2024*.xlsx"
# 创建输出目录
New-Item -ItemType Directory -Force -Path $outputDir | Out-Null
# 获取所有匹配的文件
$files = Get-ChildItem -Path $sourceDir -Filter $pattern
if ($files.Count -eq 0) {
Write-Host "未找到匹配的文件。"
exit
}
# 按月份分组
$grouped = $files | Group-Object { $_.LastWriteTime.ToString("yyyy-MM") }
foreach ($group in $grouped) {
$zipName = "$($group.Name).zip"
$zipPath = Join-Path $outputDir $zipName
Write-Host "正在创建:$zipPath"
# 创建空的 zip 文件
Compress-Archive -Path $group.Group.FullName -DestinationPath $zipPath -CompressionLevel Optimal -Force
if ($?) {
Write-Host " 成功打包 $($group.Count) 个文件。"
} else {
Write-Host " 归档失败:$zipName"
}
}
Write-Host "全部批量归档完成。"
关键点:
Get-ChildItem -Filter:高效筛选文件。Group-Object { ... }:按属性(这里按年月)对文件进行分组。Compress-Archive -Path $group.Group.FullName:将同一组内的所有文件路径一次性传给压缩命令。
免安装、跨平台的纯 Python 脚本
场景:需要在不依赖系统工具(如 zip, tar)的情况下,将指定文件夹下所有 .txt 和 .csv 文件归档为一个 zip 文件,并保持目录结构。
import os
import zipfile
from pathlib import Path
def batch_archive(source_dir, output_path, extensions=('.txt', '.csv')):
"""
批量归档指定扩展名的文件到 zip 包。
"""
source = Path(source_dir).resolve()
output_path = Path(output_path).resolve()
# 确保输出目录存在
output_path.parent.mkdir(parents=True, exist_ok=True)
with zipfile.ZipFile(str(output_path), 'w', zipfile.ZIP_DEFLATED) as zf:
# 递归遍历源目录
for file in source.rglob('*'):
if file.is_file() and file.suffix.lower() in extensions:
# arcname 用于保留相对路径
arcname = str(file.relative_to(source))
zf.write(str(file), arcname)
print(f" 已添加: {arcname}")
print(f"归档完成:{output_path}")
print(f"共添加 {len(list(zf.namelist()))} 个文件")
# 使用示例
if __name__ == "__main__":
batch_archive(
source_dir="./my_data",
output_path="./backups/data_archive.zip",
extensions=('.txt', '.csv', '.log')
)
关键点:
Path.rglob('*'):递归查找所有文件。file.relative_to(source):计算相对路径,保留目录结构。zipfile.ZIP_DEFLATED:启用压缩。- 无需安装任何第三方库,Python 自带
zipfile。
总结与选择建议
| 脚本类型 | 适用场景 | 优点 | 缺点 |
|---|---|---|---|
| Bash (tar/zip) | Linux/macOS 服务器、日志归档 | 系统自带、性能极高、适合大量文件 | Windows 需要 WSL 或 Git Bash |
| PowerShell | Windows 企业环境、Office 文档处理 | 与 .NET 深度集成、适合 Windows 系统 | Linux/macOS 不支持 |
| Python | 需要跨平台、逻辑复杂、需保留目录结构 | 跨平台、逻辑灵活、可集成数据库/邮件 | 需 Python 环境、性能略低于原生工具 |
实用建议:
- 对于日常服务器运维(日志、数据库备份),用 Bash 脚本搭配
cron定时任务最可靠。 - 对于Windows 办公场景(整理报表、项目文件),PowerShell 脚本最方便。
- 如果你在多种操作系统上工作或需要复杂的处理逻辑(如按文件名正则、按大小阈值自动压缩),Python 是最佳选择。
你只需要根据自己的操作系统和具体需求,复制上面的脚本稍作修改(主要是路径和文件类型)即可立即使用。