it-swarm.com.de

Wie finde ich die zuletzt geänderte Datei rekursiv in einem Verzeichnis?

Es scheint, dass ls die Dateien beim rekursiven Aufruf nicht korrekt sortiert:

ls -altR . | head -n 3

Wie finde ich die zuletzt geänderte Datei in einem Verzeichnis (einschließlich Unterverzeichnissen)?

212
JMW
find . -type f -printf '%[email protected] %p\n' | sort -n | tail -1 | cut -f2- -d" "

Für einen großen Baum ist es für sort möglicherweise schwierig, alles im Speicher zu behalten.

%[email protected] gibt die Änderungszeit wie ein Unix-Zeitstempel an, sort -n sortiert numerisch, tail -1 nimmt die letzte Zeile (höchster Zeitstempel), cut -f2 -d" " schneidet das erste Feld (den Zeitstempel) von der Ausgabe ab.

Edit: So wie -printf wahrscheinlich nur GNU ist, ist auch die Verwendung von stat -c bei ajreals. Obwohl es möglich ist, dasselbe mit BSD zu tun, sind die Optionen für die Formatierung unterschiedlich (-f "%m %N").

Und ich habe den Teil des Plural vermisst; Wenn Sie mehr als die neueste -Datei wünschen, müssen Sie nur das Tail-Argument aufstocken.

321
plundra

Folgend auf @ plundras Antwort , hier die BSD- und OS X-Version:

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

Anstatt die Ergebnisse zu sortieren und nur die zuletzt geänderten zu behalten, können Sie mit awk nur diejenige mit der größten Änderungszeit (in Unix-Zeit) drucken:

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

Dies sollte ein schnellerer Weg sein, um Ihr Problem zu lösen, wenn die Anzahl der Dateien groß genug ist.

Ich habe das NUL-Zeichen (d. H. '\ 0') verwendet, da ein Dateiname theoretisch ein beliebiges Zeichen (einschließlich Leerzeichen und Zeilenumbrüche) enthalten kann.

Wenn Sie in Ihrem System keine solchen pathologischen Dateinamen haben, können Sie auch das Zeilenvorschubzeichen verwenden:

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

Darüber hinaus funktioniert dies auch in mawk.

14
marco

Ich hatte die Mühe, die zuletzt geänderte Datei unter Solaris 10 zu finden. Dort hat find nicht die Option printf und stat ist nicht verfügbar. Ich habe die folgende Lösung gefunden, die für mich gut funktioniert:

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

Um den Dateinamen anzuzeigen, verwenden Sie

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

Erklärung

  • find . -type f findet alle Dateien und listet sie auf
  • sed 's/.*/"&"/' umgibt den Pfadnamen in Anführungszeichen, um Whitespaces zu behandeln
  • xargs ls -E sendet den angegebenen Pfad an ls. Die Option -E stellt sicher, dass ein vollständiger Zeitstempel (Format Jahr-Monat-Tag Stunde-Minute-Sekunden-Nanosekunden) zurückgegeben wird
  • awk '{ print $6," ",$7 }' extrahiert nur Datum und Uhrzeit
  • awk '{ print $6," ",$7," ",$9 }' extrahiert Datum, Uhrzeit und Dateiname
  • sort gibt die Dateien nach Datum sortiert zurück
  • tail -1 gibt nur die zuletzt geänderte Datei zurück
10

Dies scheint auch bei Unterverzeichnissen gut zu funktionieren:

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

Bei zu vielen Dateien den Suchvorgang verfeinern.

9
mgratia

Zeigt die neueste Datei mit vom Menschen lesbarer Zeitmarke an:

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

Ergebnis sieht so aus:

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

Ersetzen Sie -n1 durch eine höhere Nummer, um weitere Dateien anzuzeigen

6

Dies ergibt eine sortierte Liste:

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

Kehren Sie die Reihenfolge um, indem Sie im Sortierbefehl ein '-r' eingeben. Wenn Sie nur Dateinamen wünschen, fügen Sie "awk '{print $ 11}' |" ein. vor '| Kopf'

4
Karlo

Auf Ubuntu 13 ist Folgendes möglich, vielleicht ein bisschen schneller, da die Sortierung umgekehrt wird und "Kopf" anstelle von "Schwanz" verwendet wird, wodurch die Arbeit reduziert wird. So zeigen Sie die 11 neuesten Dateien in einer Baumstruktur an:

finden . -type f -printf '% T @% p\n' | sort -n -r | Kopf -11 | cut -f2- -d "" | sed -e 's, ^./,' | xargs ls -U -l

Dies führt zu einer vollständigen ls-Auflistung ohne Umsortieren und das lästige './', das 'find' für jeden Dateinamen verwendet, wird weggelassen.

Oder als Bash-Funktion:

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

Die meiste Arbeit wurde jedoch mit der ursprünglichen Lösung von plundra erledigt. Danke, Plundra.

3
RickyS

Wenn Sie stat für jede Datei einzeln ausführen, können Sie mit xargs etwas beschleunigen:

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

Dadurch wird die Änderungszeit aller Verzeichnisse im aktuellen Verzeichnis auf die neueste Datei in jedem Verzeichnis rekursiv geändert:

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

Ich verwende ständig etwas Ähnliches sowie die Top-K-Liste der zuletzt geänderten Dateien. Bei großen Verzeichnisbäumen kann es viel schneller sein, um das Sortieren zu vermeiden. Im Falle der Top-1-Datei, die zuletzt geändert wurde:

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

In einem Verzeichnis mit 1,7 Millionen Dateien bekomme ich die neueste in 3.4s, eine Beschleunigung von 7.5x gegenüber der 25.5s-Lösung mit sort.

2
Pierre D

Ich stand vor demselben Problem. Ich muss die neueste Datei rekursiv finden. Die Suche dauerte etwa 50 Minuten.

Hier ist ein kleines Skript, um es schneller zu machen:

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

Es ist eine rekursive Funktion, die das zuletzt geänderte Element eines Verzeichnisses abruft. Wenn es sich bei diesem Element um ein Verzeichnis handelt, wird die Funktion rekursiv aufgerufen und in dieses Verzeichnis usw. durchsucht.

2
AnatomicJC

Dieses einfache cli funktioniert auch:

ls -1t | head -1

Sie können -1 in die Anzahl der Dateien ändern, die Sie auflisten möchten

2
Ankit Zalani

Der folgende Befehl funktioniert unter Solaris:

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

Ich finde Folgendes kürzer und mit besser interpretierbarer Ausgabe:

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

Angesichts der festen Länge der standardisierten ISO-Formatdaten ist die lexikografische Sortierung in Ordnung und wir brauchen die -n-Option nicht für die Sortierung.

Wenn Sie die Zeitstempel wieder entfernen möchten, können Sie Folgendes verwenden:

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

So suchen Sie nach Dateien in/target_directory und all seinen Unterverzeichnissen, die in den letzten 60 Minuten geändert wurden:

$ find /target_directory -type f -mmin -60

So finden Sie die zuletzt geänderten Dateien, die in umgekehrter Reihenfolge der Aktualisierungszeit sortiert sind (d. H. Die zuletzt aktualisierten Dateien zuerst):

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

Versteckte Dateien ignorieren - mit Nice & Fast Time Stamp

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

Ergebnis

Behandelt Leerzeichen in Dateinamen gut - nicht dass diese verwendet werden sollten!

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

Mehr

Mehrfind in Hülle und Fülle dem Link folgen.

1

Ich fand den Befehl oben nützlich, aber für meinen Fall musste ich Datum und Uhrzeit der Datei anzeigen. Außerdem hatte ich ein Problem mit mehreren Dateien, die Leerzeichen in den Namen enthalten.

find . -type f -printf '%[email protected] %p\n' | sort -n | tail -1 | cut -f2- -d" " | sed 's/.*/"&"/' | xargs ls -l
1
Roger Cable

Ich habe ein pypi/github-Paket für diese Frage geschrieben, weil ich auch eine Lösung brauchte.

https://github.com/bucknerns/logtail

Installieren:

pip install logtail

Verwendung: Endet geänderte Dateien

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

Usage2: Öffnet die zuletzt geänderte Datei im Editor

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

Ich bevorzuge dieses, es ist kürzer:

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