如何從目錄中選擇資料夾中最舊的檔案

如何從目錄中選擇資料夾中最舊的檔案

我的目錄中有n很多檔案../in/。我希望從這些文件中處理最舊的文件並將其發送到../complete/目錄。其余文件將發送到該../error/目錄。有人可以幫忙嗎?

答案1

要將最舊的文件複製到../complete

cp -v "$(find ../in -maxdepth 1 -type f -printf '%T@ %p\0' | sort -zn | \
  sed -zn '1s/[0-9,\.]\+ //p')" ../complete

要將除最舊的之外的所有內容複製到../error

find ../in -maxdepth 1 -type f -printf '%T@ %p\0' | sort -zn | \
  sed -zn '2,$s/[0-9,\.]\+ //p' | xargs -0 cp -vt ../error

解釋:

  • find
    • -maxdepth 1僅下降1級;因此它不會重複搜尋目錄。
    • -type f僅匹配文件。
    • -printf '...'自訂輸出格式。%T@給出文件的最後修改時間(時間戳記),%p是文件的名稱。注意\0最後。檔案以空字節分隔列印,而不是換行分隔,因為換行可能是檔案名稱中的字符,這會破壞命令。
  • sort -zn這將讀取以空位元組分隔 ( ) 的輸出-z並按數字排序 ( -n)。
  • sed -zn讀取以空位元組分隔的輸出。
    • 1將僅匹配第一行(第一個命令)並將2,$匹配所有其他行(第二個命令)
    • s/[0-9,\.]\+ //p將從輸出中刪除前導時間戳記。
  • 僅從第二個命令:xargs -0 cp -vt ../error處理以空位元組分隔 ( ) 的輸出-0並呼叫cp -vt ../error所有輸入,這會複製檔案。

輸出範例:

$ ls -lt ../in/
total 0
-rw-r--r-- 1 user user 0 Jun 24 08:18 file2
-rw-r--r-- 1 user user 0 Jun 24 08:18 file3
-rw-r--r-- 1 user user 0 Jun 24 08:18 file4
-rw-r--r-- 1 user user 0 Jun 24 08:18 file5
-rw-r--r-- 1 user user 0 Jun 24 08:17 file_oldest
$ cp -v "$(...)" ../complete
'../in/file_oldest' -> '../complete/file_oldest'
$
$ find ... | xargs ... ../error
'../in/file2' -> '../error/file2'
'../in/file3' -> '../error/file3'
'../in/file4' -> '../error/file4'
'../in/file5' -> '../error/file5'

答案2

若要尋找最舊的檔案並將其移至所需的目錄,請使用:

# cd to ../in/

$ ls -lt | grep -v '^d' | tail -1 | awk '{print $NF}' | xargs -I '{}' mv '{}' ../complete/

現在最舊的文件已移出,您可以將所有文件移至../error/

$ mv -- * ../error/

如果您有任何以--.mv-

答案3

建立在拉胡爾的回答:

$ ls -ltr | grep -v '^d' | awk 'NR==2 {print $NF; exit}' | xargs -I '{}' mv -- '{}' ../complete/

筆記:

  • 你說你想對「最舊的文件」做一些事情。所有答案都假設您的意思是最近最少修改。如果你的意思是最近改變了, 這樣說的;答案會略有不同。如果你的意思是最近已創建,你想要的在Unix中幾乎是不可能的。
  • ls -lt(拉胡爾使用的)按修改日期/時間的順序以長格式列出當前目錄,最新的在前,最舊的在後。  ls -ltr是個r與此相反;最舊的排在最前面,最新的排在最後。
  • 如果您可能有名稱以句點 (.),將A選項加入ls;例如,ls -ltrA。 (選項的順序並不重要;您可以使用ls -ltArls -lAtr、 或者,ls -ltr -A即使您願意。)
  • 我撒了謊。ls目錄的長列表總是total先有一行。在 中ls -ltr,最舊的條目位於第二線。
  • grep -v '^d'過濾掉目錄(如果有)。
  • awk 'NR==2 { print $NF; exit }' 列印第二行(最舊的文件)的最後一個欄位(檔案名稱*),然後退出。

    • 這比 少了一個進程tail -1 | awk '{print $NF}'
    • 這可能會工作得更快,因為當awk退出時,ls也可能退出,並且您將避免產生整個目錄的清單。
    • grep你可以透過這樣​​做來消除

      ls -ltr | awk '! /^d/ { count++ } count==2 { print $NF; exit }'
      

      但我不建議這樣做。過於複雜的腳本很難維護。

  • 之後--mv xargs命令中如果您有任何以 a 開頭的檔案名,則這是必需的-
  • 你其實並不需要xargs.您可以將上面的命令簡化為

    $ mv -- $(ls -ltr | grep -v '^d' | awk 'NR==2 { print $NF; exit }') ../complete/
    

________
* 就像拉胡爾的答案一樣,如果檔案名稱包含空格或製表符,這將會失敗 - 如果檔案名稱包含換行符,情況會更糟。

如果您可能有名稱以句點 (.),shopt -s dotglob在做之前做

$ mv -- * ../error/

相關內容