2012-02-14 60 views

回答

25
BACKUPDIR=$(ls -t /backups | head -1) 

$(...)評估在子shell中的語句並返回輸出。

+7

儘管被接受並且提高了很多,但該解決方案存在幾個問題。如果目錄中的最新項目不是目錄,則不起作用。如果最新的子目錄的名稱以'。'開頭,則不起作用。如果最新的子目錄有一個包含換行符的名稱,它就不起作用。 [Shellcheck](http://www.shellcheck.net/)抱怨使用'ls'。請參閱[ParsingLs - Greg's Wiki](http://mywiki.wooledge.org/ParsingLs),瞭解處理'ls'輸出的危險性的詳細說明。 – pjh 2016-03-02 20:04:42

4

上述解決方案沒有考慮到文件正在被寫入和從目錄中刪除,導致上層目錄被返回而不是最新的子目錄。

另一個問題是,此解決方案假定該目錄只包含其他目錄而不包含正在寫入的文件。

比方說,我創建了一個名爲「test.txt的」文件,然後再次運行此命令:

echo "test" > test.txt 
ls -t /backups | head -1 
test.txt 

結果是test.txt的顯示最後一次修改的目錄了吧。

建議的解決方案「有效」,但只在最好的情況下。

假設你有一個最大1米目錄深度,更好的解決方案是使用:

find /backups/* -type d -prune -exec ls -d {} \; |tail -1 

只是交換了「/備份/」部分爲您的實際路徑。

如果你想避免顯示在bash腳本的絕對路徑,你總是可以使用這樣的事情:

LOCALPATH=/backups 
DIRECTORY=$(cd $LOCALPATH; find * -type d -prune -exec ls -d {} \; |tail -1) 
+1

儘管upvotes,此解決方案不起作用。 'find/backups/* -type d -prune -exec ...'按shell在擴展'/ backups/*'時產生的順序處理目錄。訂單由名稱決定,而不是時間戳。列出的最後一個目錄通常不會是最新的目錄。 – pjh 2016-03-02 20:41:08

0

要獲得使用ls -t最新的文件夾,您可能需要如果從文件夾中區分文件您目錄不只有目錄。用一個簡單的循環,你將有一個安全,快速的結果,並且還允許在未來輕鬆實現不同的過濾器:

while read i ; do if [ -d "${i}" ] ; then newestFolder="${i}" ; break ; fi ; done < <(ls -t) 

闡述塊:

while read currentItemOnLoop # While reading each line of the file 
do 
    if [ -d "${currentItemOnLoop}" ] # If the item is a folder 
    then 
    newestFolder="${currentItemOnLoop}" # Then save it into the "newestFolder" variable 
    break # and stop the loop 
    else 
    continue # Look for the next newest item 
    fi 
done < <(ls -t) # Sending the result of "ls -t" as a "file" to the "while read" loop 

我詳盡塊謹防continue邏輯:

else 
    continue # Look for the next newest item 

你不會使用它。我只是爲了您的知名度而將它放在那裏,因爲在這種情況下它不會影響結果。

0

嗯,我認爲這個解決方案是最有效的:

path="/my/dir/structure/*" 
backupdir=$(find $path -type d -prune | tail -n 1) 

解釋爲什麼這是一個好一點:

我們不從一個需要子殼(除用於獲取結果進入bash變量)。 我們在find命令末尾不需要無用的-exec ls -d,它已經打印出目錄列表。 我們可以很容易地改變這一點,例如排除某些模式。例如,如果您希望第二個最新的目錄,因爲備份文件被首先寫入到TMP目錄在同一路徑:

backupdir=$(find $path -type -d -prune -not -name "*temp_dir" | tail -n 1) 
+0

對我來說,這不是訂購文件夾。 – pfnuesel 2017-12-13 16:02:28

0

這1A中純巴什解決方案:

topdir=/backups 
BACKUPDIR= 

# Handle subdirectories beginning with '.', and empty $topdir 
shopt -s dotglob nullglob 

for file in "$topdir"/* ; do 
    [[ -L $file || ! -d $file ]] && continue 
    [[ -z $BACKUPDIR || $file -nt $BACKUPDIR ]] && BACKUPDIR=$file 
done 

printf 'BACKUPDIR=%q\n' "$BACKUPDIR" 

它會跳過符號鏈接,包括符號鏈接到目錄,這可能是也可能不是正確的做法。它跳過其他非目錄。它處理名稱包含任何字符的目錄,包括換行符和引導點。

13

還有就是這是一個簡單的解決方案只使用ls:按時間

BACKUPDIR=$(ls -td /backups/*/ | head -1) 
  • -t訂單(最新第一)
  • -d僅列出從該文件夾的項目
  • */只列出目錄
  • head -1返回第一項

我不知道*/,直到找到Listing only directories using ls in bash: An examination

+1

回答pjh對已接受答案的評論「如果最新的目錄以'開頭',則不起作用。」,這也與我的答案有關。如果你想包括以文件開頭的文件夾。 (但不包括./和../),您可以將ls更改爲:ls -td /backups/{.[^.],}?*/ – Martin 2017-09-14 14:37:57