mirror of
https://github.com/CodeSeeed/sbackup.git
synced 2026-10-04 02:32:58 +08:00
version 0.0.1
This commit is contained in:
1 parent
11ce6b57cb
commit
848a339512
6 files changed
+173
-1
No files matched your search
@@ -5,6 +5,7 @@ build/
|
||||
dist/
|
||||
wheels/
|
||||
*.egg-info
|
||||
.ruff_cache/
|
||||
|
||||
# Virtual environments
|
||||
.venv
|
||||
@@ -1,5 +1,10 @@
|
||||
from sbackup import run
|
||||
|
||||
def main():
|
||||
print("Hello from sbackup!")
|
||||
try:
|
||||
run()
|
||||
except KeyboardInterrupt:
|
||||
print("\nExit.")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
from .auto_save import add_folder, rm_folder, save_folder, all_folder
|
||||
import sys
|
||||
|
||||
VERSION = "0.0.1"
|
||||
help_string = f"""
|
||||
version: {VERSION}
|
||||
为你的文件保驾护航.
|
||||
|
||||
add 添加备份策略.
|
||||
rm, remove 删除备份策略.
|
||||
all 查看所有备份策略.
|
||||
save 备份所有文件夹.
|
||||
"""
|
||||
|
||||
def run():
|
||||
command: str = sys.argv[1]
|
||||
if command == "add":
|
||||
add_folder(input("备份文件夹:"), input("目标文件夹:"), input("需要忽略的文件夹或文件(用" "隔开):"))
|
||||
elif command == "rm" or command == "remove":
|
||||
rm_folder(input("目标文件夹:"))
|
||||
elif command == "all":
|
||||
folders: dict[str, str] = all_folder()
|
||||
if folders:
|
||||
for key, value in folders.items():
|
||||
print(f"{key} to {value}.")
|
||||
else:
|
||||
print("没有配置任何备份策略.")
|
||||
elif command == "save":
|
||||
save_folder()
|
||||
elif command == "version":
|
||||
print(f"version: {VERSION}.")
|
||||
elif command == "help":
|
||||
print(help_string)
|
||||
else:
|
||||
print(f"没有名为 {command} 的命令.")
|
||||
@@ -0,0 +1,53 @@
|
||||
import os
|
||||
import json
|
||||
from sbackup.pack import zip_folder
|
||||
|
||||
data = {}
|
||||
|
||||
def read_data():
|
||||
global data
|
||||
if not os.path.exists("sbackup.json"):
|
||||
with open("sbackup.json", "w", encoding="utf-8") as f:
|
||||
json.dump(data, f, ensure_ascii=False, indent=4)
|
||||
else:
|
||||
with open("sbackup.json", "r", encoding="utf-8") as f:
|
||||
data = json.load(f)
|
||||
|
||||
def write_data():
|
||||
global data
|
||||
with open("sbackup.json", "w", encoding="utf-8") as f:
|
||||
json.dump(data, f, ensure_ascii=False, indent=4)
|
||||
|
||||
def add_folder(folder_path: str, target_folder: str, skip_patterns: list[str] = [".git", "__pycache__"]):
|
||||
read_data()
|
||||
if not os.path.isdir(folder_path):
|
||||
print(f"{folder_path} 不是有效的文件夹名或不存在.")
|
||||
return
|
||||
if not os.path.isdir(target_folder):
|
||||
print(f"目标文件夹 {target_folder} 不是有效的文件夹或不存在.")
|
||||
return
|
||||
folder_path = os.path.abspath(folder_path)
|
||||
if folder_path in data.keys():
|
||||
print(f"{folder_path} 已经添加过了,请勿重复添加.")
|
||||
return
|
||||
data[folder_path] = [os.stat(folder_path).st_mtime, os.path.abspath(target_folder), skip_patterns]
|
||||
write_data()
|
||||
|
||||
def rm_folder(folder_path: str):
|
||||
read_data()
|
||||
folder_path = os.path.abspath(folder_path)
|
||||
if folder_path in data.keys():
|
||||
del data[folder_path]
|
||||
write_data()
|
||||
else:
|
||||
print(f"未找到 {folder_path} 的备份策略.")
|
||||
|
||||
def save_folder():
|
||||
read_data()
|
||||
for key, value in data.items():
|
||||
if value[0] != os.stat(key).st_mtime:
|
||||
zip_folder(key, value[1], value[2])
|
||||
|
||||
def all_folder() -> dict[str, str]:
|
||||
read_data()
|
||||
return {key: value[1] for key, value in data.items()}
|
||||
@@ -0,0 +1,70 @@
|
||||
"""
|
||||
@Time: 2025.12.20
|
||||
@Author: codeseed
|
||||
"""
|
||||
|
||||
import os
|
||||
import zipfile
|
||||
from fnmatch import fnmatch
|
||||
|
||||
|
||||
def _should_ignore(name: str, patterns: list) -> bool:
|
||||
"""检查文件/目录名是否匹配任意忽略模式"""
|
||||
for pattern in patterns:
|
||||
if fnmatch(name, pattern):
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def zip_folder(
|
||||
folder_path: str,
|
||||
zipfile_path: str = None,
|
||||
skip_patterns: list[str] = [".git", "__pycache__"],
|
||||
):
|
||||
"""
|
||||
压缩文件夹为.zip文件
|
||||
|
||||
:param folder_path: 被压缩文件夹路径
|
||||
:type folder_path: str
|
||||
:param zipfile_path: 目标.zip文件名,默认为被压缩文件夹名+.zip
|
||||
:type zipfile_path: str
|
||||
:param skip_patterns: 跳过压缩的文件或文件夹
|
||||
:type skip_patterns: list
|
||||
"""
|
||||
#print(folder_path)
|
||||
#print(zipfile_path)
|
||||
folder_path = os.path.abspath(folder_path)
|
||||
if zipfile_path is None:
|
||||
|
||||
zipfile_path = os.path.join(
|
||||
os.path.dirname(folder_path), os.path.basename(folder_path) + ".zip"
|
||||
)
|
||||
if not zipfile_path.lower().endswith(".zip"):
|
||||
#print(os.path.splitext(zipfile_path)[0])
|
||||
if not os.path.splitext(zipfile_path)[0]:
|
||||
zipfile_path = os.path.join(
|
||||
os.path.dirname(folder_path), os.path.basename(folder_path) + ".zip"
|
||||
)
|
||||
else:
|
||||
zipfile_path = os.path.splitext(zipfile_path)[0] + ".zip"
|
||||
if not os.path.isdir(folder_path):
|
||||
#print(f"{folder_path} 不是一个有效的文件夹或不存在.")
|
||||
return
|
||||
#print(folder_path)
|
||||
#print(zipfile_path)
|
||||
try:
|
||||
with zipfile.ZipFile(zipfile_path, "w", zipfile.ZIP_DEFLATED) as zipf:
|
||||
for root, dirs, files in os.walk(folder_path):
|
||||
dirs[:] = [d for d in dirs if not _should_ignore(d, skip_patterns)]
|
||||
for file in files:
|
||||
if _should_ignore(file, skip_patterns):
|
||||
continue
|
||||
file_path = os.path.join(root, file)
|
||||
arcname = os.path.relpath(file_path, os.path.dirname(folder_path))
|
||||
zipf.write(file_path, arcname)
|
||||
except PermissionError:
|
||||
print(f"权限不足:无法写入 '{zipfile_path}'")
|
||||
except OSError as e:
|
||||
print(f"系统错误:{e}")
|
||||
except Exception as e:
|
||||
print(f"未知错误:{e}")
|
||||
Reference in new issue
Block a user