
我正在開始使用rsync
它並嘗試使用它來保持本地系統上的兩個資料夾同步。我有一個來源資料夾,其內容隨著時間的推移而變化(一些文件被添加,一些文件被更改,一些被刪除)和一個目標資料夾,我希望它幾乎成為源的鏡像。所以我嘗試使用 rsync 像這樣:
rsync -a --delete "${source_dir}" "${target_dir}";
這確實使目標的內容與來源的內容完全相同。但是,我希望能夠將一些檔案新增至目標而不是來源,但我不希望每次執行 rsync 時都刪除它們。另一方面,曾經同步但後來在來源中刪除的檔案仍應刪除。
有沒有辦法做到這一點,而不必更改我想要排除的每個文件的命令?
更新:我應該提一下,我並不局限於 rsync。如果另一個程式可以完成工作,那也很好。我只是嘗試使用 rsync 來解決這個問題。
答案1
rsync
有一個名為--exclude-from
option 的選項,它允許您建立一個文件,其中包含要排除的任何文件的清單。每當您想要新增新的排除項或刪除舊的排除項時,您都可以更新此檔案。
如果您在新命令中建立排除文件,/home/user/rsync_exclude
則為:
rsync -a --delete --exclude-from="/home/user/rsync_exclude" "${source_dir}" "${target_dir}"
建立排除清單檔案時,應將每個排除規則放在單獨的行上。排除項與您的來源目錄相關。如果您的/home/user/rsync_exclude
檔案包含以下選項:
secret_file
first_dir/subdir/*
second_dir/common_name.*
secret_file
在來源目錄中呼叫的任何檔案或目錄都將被排除。- 中的任何文件都
${source_dir}/first_dir/subdir
將被排除,但空版本subdir
將被同步。 ${source_dir}/second_dir
任何帶有前綴的文件common_name.
都將被忽略。所以等等common_name.txt
common_name.jpg
答案2
既然你提到:我不限於rsync:
維護鏡像的腳本,允許向目標添加額外的文件
下面的腳本完全按照您的描述進行操作。
該腳本可以運行在冗長的mode(在腳本中設定),它將輸出備份(鏡像)的進度。不用說,這也可以用於記錄備份:
詳細選項
這個概念
1. 第一次備份時,腳本:
- 建立一個檔案(在目標目錄中),其中列出所有檔案和目錄;
.recentfiles
- 建立目標目錄中所有檔案和目錄的精確副本(鏡像)
2.上、下等備份
- 該腳本比較文件的目錄結構和修改日期。來源中的新檔案和目錄將複製到鏡像。同時建立第二個(暫存)文件,列出來源目錄中的目前文件和目錄;
.currentfiles
。 - 隨後,
.recentfiles
(列出先前備份的情況)與 進行比較.currentfiles
。僅有的.recentfiles
不在其中的檔案.currentfiles
顯然會從來源中刪除,並且將從目標中刪除。 - 您手動新增至目標資料夾的檔案無論如何都不會被腳本“看到”,並且會被單獨保留。
- 最後,臨時檔案
.currentfiles
被重新命名為.recentfiles
下一個備份週期服務,依此類推。
劇本
#!/usr/bin/env python3
import os
import sys
import shutil
dr1 = sys.argv[1]; dr2 = sys.argv[2]
# --- choose verbose (or not)
verbose = True
# ---
recentfiles = os.path.join(dr2, ".recentfiles")
currentfiles = os.path.join(dr2, ".currentfiles")
if verbose:
print("Counting items in source...")
file_count = sum([len(files)+len(d) for r, d, files in os.walk(dr1)])
print(file_count, "items in source")
print("Reading directory & file structure...")
done = 0; chunk = int(file_count/5); full = chunk*5
def show_percentage(done):
if done % chunk == 0:
print(str(int(done/full*100))+"%...", end = " ")
for root, dirs, files in os.walk(dr1):
for dr in dirs:
if verbose:
if done == 0:
print("Updating mirror...")
done = done + 1
show_percentage(done)
target = os.path.join(root, dr).replace(dr1, dr2)
source = os.path.join(root, dr)
open(currentfiles, "a+").write(target+"\n")
if not os.path.exists(target):
shutil.copytree(source, target)
for f in files:
if verbose:
done = done + 1
show_percentage(done)
target = os.path.join(root, f).replace(dr1, dr2)
source = os.path.join(root, f)
open(currentfiles, "a+").write(target+"\n")
sourcedit = os.path.getmtime(source)
try:
if os.path.getmtime(source) > os.path.getmtime(target):
shutil.copy(source, target)
except FileNotFoundError:
shutil.copy(source, target)
if verbose:
print("\nChecking for deleted files in source...")
if os.path.exists(recentfiles):
recent = [f.strip() for f in open(recentfiles).readlines()]
current = [f.strip() for f in open(currentfiles).readlines()]
remove = set([f for f in recent if not f in current])
for f in remove:
try:
os.remove(f)
except IsADirectoryError:
shutil.rmtree(f)
except FileNotFoundError:
pass
if verbose:
print("Removed:", f.split("/")[-1])
if verbose:
print("Done.")
shutil.move(currentfiles, recentfiles)
如何使用
- 將腳本複製到一個空文件中,另存為
backup_special.py
如果需要,請更改腳本頭部的詳細選項:
# --- choose verbose (or not) verbose = True # ---
使用來源和目標作為參數來運行它:
python3 /path/to/backup_special.py <source_directory> <target_directory>
速度
我在網路磁碟機 (NAS) 上的 10 GB 目錄上測試了該腳本,其中包含約 40.000 個檔案和目錄,它與 rsync 幾乎同時進行了備份。
更新中整個目錄只比 rsync 多花了幾秒鐘,處理 40.000 個文件,這在我看來是可以接受的,並不奇怪,因為腳本需要將內容與上次製作的備份進行比較。