簡體   English   中英

如何遞歸查找目錄中最新修改的文​​件?

[英]How to recursively find the latest modified file in a directory?

在進行遞歸調用時, ls似乎沒有正確對文件進行排序:

ls -altR . | head -n 3

如何在目錄(包括子目錄)中找到最近修改的文件?

find . -type f -printf '%T@ %p\n' \
| sort -n | tail -1 | cut -f2- -d" "

對於一棵巨大的樹, sort可能很難將所有內容都保存在內存中。

%T@為您提供像 unix 時間戳一樣的修改時間, sort -n按數字sort -ntail -1取最后一行(最高時間戳), cut -f2 -d" "從輸出中cut -f2 -d" "第一個字段(時間戳) .

編輯:就像-printf可能僅適用於 GNU 一樣,ajreals 對stat -c也是如此。 雖然可以在 BSD 上做同樣的事情,但格式化的選項是不同的( -f "%m %N"看起來)

我錯過了復數部分; 如果您想要更多然后最新文件,只需增加 tail 參數。

跟進@plundra 的回答,這里是 BSD 和 OS X 版本:

find . -type f -print0 \
| xargs -0 stat -f "%m %N" \
| sort -rn | head -1 | cut -f2- -d" "

您可以使用 awk 僅打印修改時間最長的結果(在 unix 時間),而不是對結果進行排序並僅保留最后修改的結果:

find . -type f -printf "%T@\0%p\0" | awk '
    {
        if ($0>max) {
            max=$0; 
            getline mostrecent
        } else 
            getline
    } 
    END{print mostrecent}' RS='\0'

如果文件數量足夠大,這應該是解決問題的更快方法。

我使用了 NUL 字符(即 '\\0'),因為理論上,文件名可以包含除此之外的任何字符(包括空格和換行符)。

如果您的系統中沒有這樣的病態文件名,您也可以使用換行符:

find . -type f -printf "%T@\n%p\n" | awk '
    {
        if ($0>max) {
            max=$0; 
            getline mostrecent
        } else 
            getline
    } 
    END{print mostrecent}' RS='\n'

此外,這也適用於 mawk。

這似乎工作正常,即使有子目錄:

find . -type f | xargs ls -ltr | tail -n 1

如果文件太多,請細化查找。

我在 Solaris 10 下很難找到最后修改的文件。 find沒有printf選項並且stat不可用。 我發現以下解決方案對我很有效:

find . -type f | sed 's/.*/"&"/' | xargs ls -E | awk '{ print $6," ",$7 }' | sort | tail -1

要顯示文件名以及使用

find . -type f | sed 's/.*/"&"/' | xargs ls -E | awk '{ print $6," ",$7," ",$9 }' | sort | tail -1

解釋

  • find . -type f find . -type f查找並列出所有文件
  • sed 's/.*/"&"/'將路徑名用引號括起來以處理空格
  • xargs ls -E將引用的路徑發送到ls-E選項確保返回完整的時間戳(格式年-月-日時-分-秒-納秒
  • awk '{ print $6," ",$7 }'只提取日期和時間
  • awk '{ print $6," ",$7," ",$9 }'提取日期、時間和文件名
  • sort返回按日期sort的文件
  • tail -1只返回最后修改的文件

顯示具有人類可讀時間戳的最新文件:

find . -type f -printf '%TY-%Tm-%Td %TH:%TM: %Tz %p\n'| sort -n | tail -n1

結果如下所示:

2015-10-06 11:30: +0200 ./foo/bar.txt

要顯示更多文件,請將-n1替換為更大的數字

我一直使用類似的東西,以及最近修改過的文件的前 k 列表。 對於大型目錄樹,避免排序快得多 在只有 top-1 最近修改的文件的情況下:

find . -type f -printf '%T@ %p\n' | perl -ne '@a=split(/\s+/, $_, 2); ($t,$f)=@a if $a[0]>$t; print $f if eof()'

在包含 170 萬個文件的目錄中,我在 3.4 秒內獲得了最新的一個,與使用排序的 25.5 秒解決方案相比,速度提高了 7.5 倍。

這給出了一個排序列表:

find . -type f -ls 2>/dev/null | sort -M -k8,10 | head -n5

通過在排序命令中放置“-r”來顛倒順序。 如果您只想要文件名,請插入“awk '{print $11}' |” '| 之前頭'

在 Ubuntu 13 上,以下是這樣做的,可能會快一點,因為它顛倒了排序並使用“head”而不是“tail”,從而減少了工作。 要在樹中顯示 11 個最新文件:

尋找 。 -type f -printf '%T@ %p\\n' | 排序 -n -r | 頭-11 | cut -f2- -d" " | sed -e 's,^./,,' | xargs ls -U -l

這給出了一個完整的 ls 列表,無需重新排序,並省略了 'find' 放在每個文件名上的煩人的 './'。

或者,作為 bash 函數:

treecent () {
  local numl
  if [[ 0 -eq $# ]] ; then
    numl=11   # Or whatever default you want.
  else
    numl=$1
  fi
  find . -type f -printf '%T@ %p\n' | sort -n -r | head -${numl} |  cut -f2- -d" " | sed -e 's,^\./,,' | xargs ls -U -l
}

盡管如此,大部分工作還是由 plundra 的原始解決方案完成的。 謝謝普倫德拉。

我遇到了同樣的問題。 我需要遞歸地找到最新的文件。 find 花了大約 50 分鍾才找到。

這是一個小腳本,可以更快地完成它:

#!/bin/sh

CURRENT_DIR='.'

zob () {
    FILE=$(ls -Art1 ${CURRENT_DIR} | tail -n 1)
    if [ ! -f ${FILE} ]; then
        CURRENT_DIR="${CURRENT_DIR}/${FILE}"
        zob
    fi
    echo $FILE
    exit
}
zob

這是一個遞歸函數,它獲取目錄的最新修改項。 如果此項是目錄,則遞歸調用該函數並搜索該目錄等。

我發現以下內容更短且具有更多可解釋的輸出:

find . -type f -printf '%TF %TT %p\n' | sort | tail -1

鑒於標准化 ISO 格式日期時間的固定長度,字典排序很好,我們不需要-n選項進行排序。

如果要再次刪除時間戳,可以使用:

find . -type f -printf '%TFT%TT %p\n' | sort | tail -1 | cut -f2- -d' '

如果單獨在每個文件上運行stat會變慢,您可以使用xargs來加快速度:

find . -type f -print0 | xargs -0 stat -f "%m %N" | sort -n | tail -1 | cut -f2- -d" " 

這將遞歸地將當前目錄中所有目錄的修改時間更改為每個目錄中的最新文件:

for dir in */; do find $dir -type f -printf '%T@ "%p"\n' | sort -n | tail -1 | cut -f2- -d" " | xargs -I {} touch -r {} $dir; done

這個簡單的 cli 也可以工作:

ls -1t | head -1

您可以將 -1 更改為要列出的文件數

我發現上面的命令很有用,但就我而言,我還需要查看文件的日期和時間,我遇到了幾個名稱中包含空格的文件的問題。 這是我的工作解決方案。

find . -type f -printf '%T@ %p\n' | sort -n | tail -1 | cut -f2- -d" " | sed 's/.*/"&"/' | xargs ls -l

我更喜歡這個,它更短:

find . -type f -print0|xargs -0 ls -drt|tail -n 1

以下命令適用於 Solaris :

find . -name "*zip" -type f | xargs ls -ltr | tail -1 

我為這個問題寫了一個 pypi/github 包,因為我也需要一個解決方案。

https://github.com/bucknerns/logtail

安裝:

pip install logtail

用法:尾部更改的文件

logtail <log dir> [<glob match: default=*.log>]

用法2:在編輯器中打開最新更改的文件

editlatest <log dir> [<glob match: default=*.log>]

忽略隱藏文件 - 帶有漂亮且快速的時間戳

以下是如何在具有子目錄的目錄中查找和列出最新修改的文​​件。 故意忽略隱藏文件。 時間格式可以自定義。

$ find . -type f -not -path '*/\.*' -printf '%TY.%Tm.%Td %THh%TM %Ta %p\n' |sort -nr |head -n 10

結果

很好地處理文件名中的空格 - 不應該使用這些!

2017.01.25 18h23 Wed ./indenting/Shifting blocks visually.mht
2016.12.11 12h33 Sun ./tabs/Converting tabs to spaces.mht
2016.12.02 01h46 Fri ./advocacy/2016.Vim or Emacs - Which text editor do you prefer?.mht
2016.11.09 17h05 Wed ./Word count - Vim Tips Wiki.mht

更多的

find鏈接下面的稱譽。

要在 /target_directory 及其所有子目錄中搜索最近 60 分鍾內修改過的文件:

$ find /target_directory -type f -mmin -60

查找最近修改的文件,按更新時間倒序排序(即最近更新的文件排在前):

$ find /etc -type f -printf '%TY-%Tm-%Td %TT %p\n' | sort -r

在使用基於find的解決方案多年后,我發現自己希望能夠排除.git類的.git

我切換到這個基於rsync的解決方案。 把它放在~/bin/findlatest

#!/bin/sh
# Finds most recently modified files.
rsync -rL --list-only "$@" | grep -v '^d' | sort -k3,4r | head -5

現在findlatest . 將列出 5 個最近修改的文件,並findlatest --exclude .git . 將列出.git排除的 5 個。

這是通過利用一些很少使用的 rsync 功能來實現的: “如果在沒有目標的情況下指定 [to rsync] 單個源 arg,則文件將以類似於 ls -l 的輸出格式列出”rsync手冊頁)。

與基於 rsync 的備份工具結合使用 rsync args 的能力非常有用。 例如,我使用rsnapshot ,並使用rsnapshot.conf行備份應用程序目錄:

backup  /var/atlassian/application-data/jira/current/   home    +rsync_long_args=--archive --filter="merge /opt/atlassian/jira/current/backups/rsync-excludes"

其中rsync-excludes列出了我不想備份的目錄:

- log/
- logs/
- analytics-logs/
- tmp/
- monitor/*.rrd4j

我現在可以看到將要備份的最新文件:

findlatest /var/atlassian/application-data/jira/current/ --filter="merge /opt/atlassian/jira/current/backups/rsync-excludes"

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM