2010-08-16 83 views
6

我是shell腳本編程新手,所以我需要一些幫助,需要如何解決這個問題。獲取基於時間戳的最新文件

我有一個目錄,其中包含以下格式的文件。這些文件位於一個名爲/ incoming/external/data的目錄中

AA_20100806.dat 
AA_20100807.dat 
AA_20100808.dat 
AA_20100809.dat 
AA_20100810.dat 
AA_20100811.dat 
AA_20100812.dat 

正如您所見,文件的文件名包含一個時間戳。即[RANGE] _ [YYYYMMDD] .dat

我需要做的是找出哪些文件具有最新日期使用文件名上的時間戳而不是系統時間戳,並將文件名存儲在變量中並將其移動到另一個目錄並將其餘目錄移到其他目錄。

+0

能[RANGE]是兩個字符的任意組合?這會產生很大的不同,因爲您可能會注意到已經給出的答案。 – 2010-08-16 17:38:13

+0

是的,他們可以不同。同樣的文件夾將包含其他類型的文件,名稱不像上面所示。 – ziggy 2010-08-18 09:17:19

回答

17

對於那些誰只是想要一個答案,那就是:

ls | sort -n -t _ -k 2 | tail -1 

這裏的這引發了我的思考過程。

我打算假設[範圍]部分可以是任何東西。

從我們所知道的開始。

  • 工作目錄:/傳入/外部/數據
  • 的文件格式:[RANGE] _ [YYYYMMDD] .DAT

我們需要找到最近的[YYYYMMDD]文​​件該目錄,我們需要存儲該文件名。

可用的工具(我只列出了相關的工具,這個問題...識別他們的做法變得更容易):

我想我們不需要sed,因爲我們可以使用ls命令的整個輸出。使用ls命令時,awk,排序和尾部我們可以得到正確的文件像這樣(要記住,你必須要檢查你的OS將接受語法):

NEWESTFILE=`ls | awk -F_ '{print $1 $2}' | sort -n -k 2,2 | tail -1` 

然後,它只是一個問題把下劃線放回去,這不應該太難。

編輯:我有一點時間,所以我開始修復命令,至少在Solaris中使用。

下面是令人費解的第一遍(假定目錄中的所有文件格式相同:[RANGE] _ [yyyymmdd] .dat)。我打賭有更好的方法來做到這一點,但是這可與我自己的測試數據(其實,我發現剛纔一個更好的辦法,見下文):

ls | awk -F_ '{print $1 " " $2}' | sort -n -k 2 | tail -1 | sed 's/ /_/' 

...在寫這一點, ,我發現你可以這樣做:

ls | sort -n -t _ -k 2 | tail -1 

我會把它分解成幾部分。

ls 

夠簡單...獲取目錄列表,只是文件名。現在我可以將它轉化爲下一個命令。

awk -F_ '{print $1 " " $2}' 

這是AWK命令。它允許您採用輸入行並以特定方式對其進行修改。在這裏,我所做的只是指定awk應該在有下劃線(_)的地方打破輸入。我使用-F選項執行此操作。這給了我每個文件名的兩半。然後我告訴awk輸出前半部分($ 1),後面跟着一個空格(「」) ,接着是下半部分($ 2)。請注意,該空間是我最初建議中缺少的部分。而且,這是不必要的,因爲您可以在下面的排序命令中指定分隔符。

現在輸出在每行上分割爲[RANGE] [yyyymmdd] .dat。現在我們可以對此進行分類:

sort -n -k 2 

這需要輸入並根據第二個字段進行排序。 sort命令默認使用空格作爲分隔符。在編寫此更新時,我找到了用於排序的文檔,它允許您指定分隔符,所以AWK和SED是不必要的。取ls並通過以下排序管道:

sort -n -t _ -k 2 

這可以達到相同的結果。現在,你只需要最後一個文件,所以:

tail -1 

如果使用awk來分隔文件(這僅僅是增加額外的複雜性,所以不要做羞怯),你可以替換的空間一個下劃線再次與sed:

sed 's/ /_/' 

這裏有一些很好的信息,但我相信大多數人不會像這樣讀到底部。

+0

我試過這個,但它沒有奏效。你能解釋一下它究竟做了什麼。謝謝 – ziggy 2010-08-17 11:04:26

+0

好吧,我在測試後更新了。我不得不在我的awk命令中修復一些東西,然後發現它真的不需要。解決方案處於頂端,解釋很長且沒有必要,但我喜歡寫它。 – 2010-08-17 16:44:52

+0

適合我。請有我的寶貝。 – 2013-04-12 22:11:28

2

嘗試:

$ ls -lr 

希望它能幫助。

+0

嗨,不會使用該文件的系統時間戳進行排序嗎?我對實際文件名的時間戳感興趣。 謝謝 – ziggy 2010-08-16 17:33:31

+0

不,它會根據您的區域設置按名稱對文件進行排序。如果你想按系統時間戳排序,你需要'-t'標誌。 – igor 2010-08-16 17:38:56

1

用途:

ls -r -1 AA_*.dat | head -n 1 

(假設沒有其他文件匹配AA_*.dat

3

這應該工作:

newest=$(ls | sort -t _ -k 2,2 | tail -n 1) 
others=($(ls | sort -t _ -k 2,2 | head -n -1)) 

mv "$newest" newdir 
mv "${others[@]}" otherdir 

如果有文件名中的空格它不會工作,雖然你可以修改IFS變量影響。

+0

嗨,圓括號是什麼? – ziggy 2010-08-17 14:39:01

+0

@ziggy:你的意思是第二行的外部設置?他們創建一個數組,用於最後一行。 – 2010-08-17 14:41:49

+0

喜丹尼斯, 我指的兩個內外圓括弧。我試着運行上述內容,但括號導致語法錯誤。我正在使用Bourne shell。這些korn shell特定的結構是什麼? – ziggy 2010-08-17 16:14:20

1

由於文件的命名約定,按字母順序是一樣的日期順序。我敢肯定,在慶典「*」膨脹出字母(但無法找到在手冊中的任何證據),LS當然不會,所以用最新日期的文件,將按照字母順序的最後一個。

因此,在慶典

mv $(ls | tail -1) first-directory 
mv * second-directory 

應該做的伎倆。

如果您想更具體的有關文件的選擇,然後用別的東西代替* - 例如AA_*.dat

+0

這也適用,但我試圖避免依靠系統爲我進行排序(即通過ls cmd)。謝謝 – ziggy 2010-08-17 14:39:29

+0

爲什麼你不想依賴'ls' - 你的'系統'是什麼意思? – Beano 2010-08-17 16:25:58

1

我的這個解決方案類似於人,但更簡單一點。

ls -tr | tail -1 

實際做的是依靠ls對輸出進行排序,然後使用tail獲取最後列出的文件名。

,如果你需要的文件名有一個前導點這個解決方案將無法正常工作(例如.profile文件)。如果文件名包含空格

這個解決方案確實工作。