Jak rekurencyjnie znaleźć ostatnio zmodyfikowany plik w katalogu?

Wygląda na to, że ls nie sortuje poprawnie plików podczas wywołania rekurencyjnego:

ls -altR . | head -n 3

Jak mogę znaleźć ostatnio zmodyfikowany plik w katalogu (łącznie z podkatalogami)?

Author: mwfearnley, 2010-12-30

19 answers

find . -type f -printf '%T@ %p\n' | sort -n | tail -1 | cut -f2- -d" "
Dla ogromnego drzewa może być trudno zachować wszystko w pamięci.

%T@ daje Ci czas modyfikacji jak uniksowy znacznik czasu, sort -n sortuje numerycznie, tail -1 pobiera ostatnią linię (najwyższy znacznik czasu), cut -f2 -d" " odcina pierwsze pole (znacznik czasu) z wyjścia.

Edit: tak jak {[6] } jest prawdopodobnie tylko GNU, ajreals używa stat -c również. Chociaż na BSD można zrobić to samo, opcje formatowania są inne (-f "%m %N" to seem)

I przegapiłem część liczby mnogiej; jeśli chcesz więcej to najnowszy plik , po prostu podnieś argument ogonowy.

 308
Author: plundra,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-12-30 11:01:06

Po odpowiedzi@plundra, oto wersja BSD i OS X:

find . -type f -print0 | xargs -0 stat -f "%m %N" |
sort -rn | head -1 | cut -f2- -d" "
 113
Author: Emerson Farrugia,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:10:33

Zamiast sortować wyniki i przechowywać tylko te Ostatnio zmodyfikowane, możesz użyć awk, aby wydrukować tylko ten z największym czasem modyfikacji (w czasie Uniksa):

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

To powinien być szybszy sposób rozwiązania problemu, jeśli liczba plików jest wystarczająco duża.

Użyłem znaku NUL (np. '\0'), ponieważ teoretycznie nazwa pliku może zawierać dowolny znak (w tym spację i znak nowej linii).

Jeśli nie masz takich patologicznych nazw plików w systemie można również użyć znaku nowej linii:

find . -type f -printf "%T@\n%p\n" | awk '
    {
        if ($0>max) {
            max=$0; 
            getline mostrecent
        } else 
            getline
    } 
    END{print mostrecent}' RS='\n'
Ponadto działa to również w mawk.
 14
Author: marco,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-09-28 14:11:30

Miałem problem ze znalezieniem ostatnio zmodyfikowanego pliku pod Solarisem 10. Tam find nie ma opcji printf i stat nie jest dostępna. Odkryłem następujące rozwiązanie, które działa dobrze dla mnie:

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

Aby wyświetlić nazwę pliku użyj

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

Wyjaśnienie

  • find . -type f wyszukuje i wyświetla wszystkie pliki
  • sed 's/.*/"&"/' zawija ścieżkę w cudzysłowy, aby obsłużyć białe spacje
  • xargs ls -E wysyła cytowaną ścieżkę do ls, opcji -E upewnij się, że zwracany jest pełny znacznik czasu (format Rok-Miesiąc-Dzień godzina-minuta-sekundy-nanosekundy)
  • awk '{ print $6," ",$7 }' wypisuje tylko datę i czas
  • awk '{ print $6," ",$7," ",$9 }' wypisuje datę, czas i nazwę pliku
  • sort zwraca pliki posortowane według daty
  • tail -1 zwraca tylko ostatnio zmodyfikowany plik
 9
Author: Florian Feldhaus,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-09-05 16:08:45

To wydaje się działać dobrze, nawet z podkatalogami:

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

W przypadku zbyt wielu plików, doprecyzuj znalezisko.

 9
Author: mgratia,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-11-29 16:19:03

Pokazuje najnowszy plik z czytelnym dla człowieka znacznikiem czasu:

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

Wynik wygląda następująco:

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

Aby wyświetlić więcej plików, zastąp -n1 wyższą liczbą

 6
Author: Fabian Schmengler,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-10-08 08:50:46

To daje posortowaną listę:

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

Odwróć kolejność, umieszczając '- r' w Komendzie sortowania. Jeśli chcesz tylko nazwy plików, Wstaw "awk' {print $11} | / "przed' / head '

 4
Author: Karlo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-01-30 15:27:21

Na Ubuntu 13, poniżej robi to, może trochę szybciej, ponieważ odwraca sortowanie i używa "głowy" zamiast "ogona", zmniejszając pracę. Aby wyświetlić 11 najnowszych plików w drzewie:

Znajdź . - type f-printf '%T@ %P\n' | sort-n-r | head -11 | cut-f2- -d" " | sed-e 'S,^.| ,, '/xargs ls-U-L

Daje to pełną listę ls bez ponownego sortowania i pomija irytujące './ 'że' find ' umieszcza nazwę KAŻDEGO pliku.

Lub, jako bash Funkcja:

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
}
Mimo to większość prac została wykonana przez oryginalne rozwiązanie plundry. Dzięki plundra.
 3
Author: RickyS,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-11-14 13:23:15

To rekurencyjnie zmienia czas modyfikacji wszystkich katalogów w bieżącym katalogu na najnowszy plik w każdym katalogu:

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
 2
Author: rwhirn,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-05-06 00:20:50

Ten prosty cli będzie również działać:

ls -1t | head -1

Możesz zmienić -1 na liczbę plików, które chcesz wyświetlić

 2
Author: Ankit Zalani,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-08-05 09:39:13

Miałem do czynienia z tym samym problemem. Muszę rekurencyjnie znaleźć najnowszy plik. znalezienie zajęło około 50 minut.

Oto mały skrypt, aby zrobić to szybciej:

#!/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

Jest to funkcja rekurencyjna, która pobiera ostatnio zmodyfikowaną pozycję katalogu. Jeśli ten element jest katalogiem, funkcja jest wywoływana rekurencyjnie i przeszukiwana do tego katalogu, itd.

 2
Author: AnatomicJC,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-10-29 14:47:33

Używam czegoś podobnego cały czas, a także top-K listy ostatnio zmodyfikowanych plików. W przypadku dużych drzew katalogów można znacznie szybciej uniknąć sortowania . W przypadku tylko top-1 Ostatnio zmodyfikowanego pliku:

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

Na katalogu zawierającym 1,7 miliona plików, najnowszy dostaję w 3,4 s, przyspieszenie 7,5 x w porównaniu z rozwiązaniem 25,5 s za pomocą sortowania.

 2
Author: Pierre D,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-03-15 22:52:12

Jeśli uruchamianie stat na każdym pliku z osobna ma spowolnić, możesz użyć xargs, aby nieco przyspieszyć:

find . -type f -print0 | xargs -0 stat -f "%m %N" | sort -n | tail -1 | cut -f2- -d" " 
 1
Author: Mattias Wadman,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-10-10 12:08:08

Powyższe polecenie okazało się przydatne, ale w moim przypadku musiałem zobaczyć datę i godzinę pliku, a także miałem problem z kilkoma plikami, które mają spacje w nazwach. Oto moje rozwiązanie.

find . -type f -printf '%T@ %p\n' | sort -n | tail -1 | cut -f2- -d" " | sed 's/.*/"&"/' | xargs ls -l
 1
Author: Roger Cable,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-12-17 15:08:53

Na Solarisie działało następujące polecenie:

find . -name "*zip" -type f | xargs ls -ltr | tail -1 
 1
Author: RahulM,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-11-23 12:30:42

Wolę ten, jest krótszy:

find . -type f -print0|xargs -0 ls -drt|tail -n 1
 0
Author: user3295940,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-02-11 06:36:21

Napisałem pakiet pypi / github na to pytanie, ponieważ również potrzebowałem rozwiązania.

Https://github.com/bucknerns/logtail

Zainstaluj:

pip install logtail

Usage: tails changed files

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

Usage2: otwiera ostatnio zmieniony plik w edytorze

editlatest <log dir> [<glob match: default=*.log>]
 0
Author: Nathan Buckner,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-08-12 19:05:48

Ignorowanie ukrytych plików-z ładnym i szybkim znacznikiem czasu

Dobrze obsługuje spacje w nazwach plików-nie powinieneś ich używać!

$ 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

Więcejfind galore można znaleźć klikając na link.

 0
Author: Serge Stroobandt,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-01-28 06:35:19

Znajduję następujące krótsze i bardziej interpretowalne wyjście:

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

Biorąc pod uwagę stałą długość znormalizowanego formatu ISO, sortowanie leksykograficzne jest w porządku i nie potrzebujemy opcji -n na sortowaniu.

Jeśli chcesz ponownie usunąć znaczniki czasu, możesz użyć:

find . -type f -printf '%TFT%TT %p\n' | sort | tail -1 | cut -f2- -d' '
 0
Author: snth,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-06-07 14:26:32