2008-09-24 90 views
2

我有一臺帶有兩個目錄樹的計算機A.第一個目錄包含跨越幾年的原始模型日期。第二個目錄是第一個目錄的副本和幾個附加文件。還有第二臺計算機包含一個與計算機A上的第二個目錄相同的目錄樹(新的mod時間和附加文件)。如何更新兩臺機器上兩個較新目錄中的文件,以便文件的修改時間與原始文件相同?請注意,這些目錄樹大小爲10 GB,所以解決方案必須包含一些僅向第二臺計算機發送日期信息的方法。跨多個目錄的同步文件修改時間

回答

0

我認爲rsync的(與正確的選項) 將做到這一點 - 它聲稱只發送 文件差異,所以想必 工作了,有沒有差異 轉移。

- 次保留修改時間,這是你想要的。

見(例如) http://linux.die.net/man/1/rsync

同時添加-I,--ignore次不跳過匹配的大小和時間

使所有文件「轉移」和信任的文件rsync的的文件不同的優化,以使其「相當有效。」 - 節選看到從下面的man page

-t,--times 這告訴rsync的傳輸與文件一起修改時間和更新它們的遙控器上SYST EM。請注意,如果未使用此選項,排除未被修改的文件的優化將無法生效;換句話說,缺少-t或-a將導致下一次傳輸的行爲就像使用-I一樣,導致所有文件都被更新(儘管如果文件沒有真正改變,rsync算法會使更新效率更高,你使用-t)會好得多。

+0

其實rsync使用日期/時間來決定是否有差異(它只會同步文件具有較新的mod本地的日期比遠程);你不能使用rsync來做這件事。此外rsync不會同步任何東西,除非它決定同步文件內容,並且這被排除在提問者之外。 – Mecki 2008-09-24 17:08:14

1

我會瀏覽源目錄樹中的所有文件,並將修改時間從它們收集到可以在其他目錄樹上運行的腳本中。你需要小心幾個'陷阱'。首先,確保您的輸出腳本具有相對路徑,並確保您從適當的目標目錄(它應該是目標樹的根目錄)運行它。另外,在更換機器時,請確保您使用的是與生成腳本的計算機上相同的時區。

下面是我放在一起的Perl腳本,它將輸出需要更新其他目錄樹上的時間的touch命令。根據目標機器的不同,您可能需要調整日期格式或命令選項,但這應該給您一個啓動的地方。

#!/usr/bin/perl 

my $STARTDIR="$HOME/test"; 

chdir $STARTDIR; 
my @files = `find . -type f`; 
chomp @files; 

foreach my $file (@files) { 
    my $mtime = localtime((stat($file))[9]); 
    print qq(touch -m -d "$mtime" "$file"\n); 
} 
1

另一種方法,你可以嘗試是使用NFS來連接遠程目錄,然後使用findtouch -r複製倍。

2

以下命令將確保TEST2獲得分配了TEST1具有

touch -t `stat -t '%Y%m%d%H%M.%S' -f '%Sa' TEST1` TEST2 

現在不是這裏使用硬編碼值相同的日期,你可以使用「查找」工具,然後運行查找文件通過遠程計算機上的SSH進行觸摸。但是,這意味着您可能必須輸入每個文件的密碼,除非您將SSH切換爲證書驗證。我寧願不要在一個超級花式的單線上做這一切。相反,讓我們使用臨時文件。首先進入有問題的目錄並運行一個查找(你可以根據文件類型,大小,擴展名進行過濾,無論你喜歡什麼,請參閱「man find」以獲取詳細信息。我只是通過類型文件進行過濾以排除任何目錄):

find . -type f -print -exec stat -t '%Y%m%d%H%M.%S' -f '%Sm' "{}" \; > /tmp/original_dates.txt 

現在我們有一個看起來像這樣的文件(在我的例子中,只有兩個項目有):

# cat /tmp/original_dates.txt 
./test1 
200809241840.55 
./test2 
200809241849.56 

現在只要將文件在拷貝到其他機器,並將其放置在目錄(以便相對文件路徑匹配)並應用日期:

cat original_dates.txt | (while read FILE && read DATE; do touch -t $DATE "$FILE"; done) 

也可以使用包含空格的文件名。

其中一個注意事項:我使用stat中的最後一個「修改」日期,因爲這是您在問題中寫的內容。然而,聽起來好像你想使用「創建」日期(每個文件都有一個創建日期,最後修改日期和最後訪問日期),你需要稍微改變統計調用。

'%Sm' - last modification date 
'%Sc' - creation date 
'%Sa' - last access date 

然而,觸摸只能更改修改時間和訪問時間,我覺得它不能改變文件的創建時間......因此,如果這是你的真實意圖,我的解決方案可能是分最佳...但在這種情況下,您的問題也是如此;-)

+0

我最後不得不使用touch new_file -t \`date -d @ \``stat -t -c「%Y」old_file \\`+%Y%m%d%H%M%S \` – kormoc 2012-06-06 21:23:02

2

Paul的答案部分正確,rsync是能夠做到這一點,但具有不同的參數。正確的命令是

rsync -Prt --size-only original_dir copy_dir 

其中-P使局部傳輸和顯示進度指示,-r遞歸通過子目錄,-t保留時間標記和--size-only不轉移匹配大小的文件。

0

我改用下面的Python腳本。

Python腳本的運行速度比爲每個文件創建新進程的方法快得多(如使用findstat)。下面的解決方案也適用於系統之間的時區差異,因爲它使用UTC時間。它也適用於包含空格的路徑(但不包含包含換行符的路徑!)。它不會爲符號鏈接設置時間,因爲the operating system provides no mechanism to modify the timestamp of a symlink,但是在文件管理器中,符號鏈接指向的文件時間反而顯示。它使用maxTime參數來避免重置從原始目錄複製後實際修改的文件的日期。

listMTim​​es.py:

import os 
from datetime import datetime 
from pytz import utc 

for dirpath, dirnames, filenames in os.walk('./'): 
    for name in filenames+dirnames: 
     path = os.path.join(dirpath, name) 
     # Avoid symlinks because os.path.getmtime and os.utime get and 
     # set the time of the pointed file, and in the new directory, 
     # the link may have been redirected. 
     if not os.path.islink(path): 
      mtime = datetime.fromtimestamp(os.path.getmtime(path), utc) 
      print(mtime.isoformat()+" "+path) 

setMTim​​es。PY:

import datetime, fileinput, os, sys, time 
import dateutil.parser 
from pytz import utc 

# Based on 
# http://stackoverflow.com/questions/6999726/python-getting-millis-since-epoch-from-datetime 
def unix_time(dt): 
    epoch = datetime.datetime.fromtimestamp(0, utc) 
    delta = dt - epoch 
    return delta.total_seconds() 

if len(sys.argv) != 2: 
    print('Syntax: '+sys.argv[0]+' <maxTime>') 
    print(' where <maxTime> an ISO time, e. g. "2013-12-02T23:00+02:00".') 
    exit(1) 

# A file with modification time newer than maxTime is not reset to 
# its original modification time. 
maxTime = unix_time(dateutil.parser.parse(sys.argv[1])) 

for line in fileinput.input([]): 
    (datetimeString, path) = line.rstrip('\r\n').split(' ', 1) 
    mtime = dateutil.parser.parse(datetimeString) 
    if os.path.exists(path) and not os.path.islink(path): 
     if os.path.getmtime(path) <= maxTime: 
      os.utime(path, (time.time(), unix_time(mtime))) 

用法:在第一目錄(原)運行

python listMTimes.py >/tmp/original_dates.txt 

然後在第二目錄(原始的一個副本,可能會進行一些修改過的文件/加入/刪除)運行這樣的事情:

python setMTimes.py 2013-12-02T23:00+02:00 </tmp/original_dates.txt 
相關問題