Trouver le dernier fichier par date de modification

29

Si je souhaite trouver le dernier fichier (mtime) dans un (grand) répertoire contenant des sous-répertoires, comment procéderai-je?

Beaucoup de messages que j'ai trouvés suggèrent une variation de ls -lt | head (curieusement, beaucoup suggèrent ls -ltr | tail qui est identique mais moins efficace), ce qui est correct sauf si vous avez des sous-répertoires (ce que je fais).

Là encore, vous pourriez

find . -type f -exec ls -lt \{\} \+ | head

qui fera certainement l'affaire pour autant de fichiers pouvant être spécifiés par une commande, c'est-à-dire que si vous avez un répertoire grand , -exec...\+ émettra des commandes distinctes; par conséquent, chaque groupe sera trié par ls à l'intérieur de lui-même, mais pas sur l'ensemble total; la tête récupérera donc la dernière entrée du premier lot.

Des réponses?

    
posée Rich 13.09.2011 - 11:22
la source

6 réponses

38

Vous n'avez pas besoin de recourir à des commandes externes (en tant que ls ) car find peut faire tout ce dont vous avez besoin via l'action -printf :

find /path -printf '%T+ %p\n' | sort -r | head
    
réponse donnée enzotib 13.09.2011 - 11:29
la source
7

J'ai eu un problème similaire aujourd'hui, mais je l'ai attaqué sans find . J'avais besoin de quelque chose de court, je pouvais courir sur ssh pour retourner le fichier le plus récemment édité dans mon répertoire personnel. C’est à peu près ce que j’ai trouvé:

ls -tp | grep -v /$ | head -1

L'option -p de ls ajoute une barre oblique finale aux répertoires, le grep -v supprime les lignes se terminant par une barre oblique (autrement dit, tous les répertoires) et head -1 limite la sortie à un seul fichier.

Cela est beaucoup moins détaillé que d'utiliser find si tout ce que vous voulez renvoyer est le nom du fichier.

    
réponse donnée Pat Regan 10.01.2013 - 17:42
la source
3

Ceci est sur mon système plus rapide que printf , bien que je ne comprenne pas pourquoi

find /path -type f -exec stat -c "%y %n" {} + | sort -r | head
    
réponse donnée arrange 13.09.2011 - 11:46
la source
1

Ce n'est pas aussi à la mode, mais il est également possible d'y parvenir avec Midnight Commander : recherchez *, personnalisez le résultat, triez par date de modification dans l'ordre inverse.

Évidemment, c'est un peu plus lent que find - mon répertoire de base, contenant 922 000 fichiers, a été trié par mc en presque 14 minutes, tandis que find a dépensé moins de 5 -, mais présente certains avantages:

  • Je passerais probablement plus de temps que la différence de 9 minutes à inventer une invocation de recherche appropriée:)

  • moins de risque d'erreur (j'ai oublié de spécifier -r pour le tri, etc. - recommencez)

  • il est possible de jouer avec le jeu de résultats en modifiant l'ordre de tri, etc. - sans interroger à nouveau les fichiers.

  • possible d'effectuer des opérations de fichier uniquement sur certains fichiers du jeu de résultats - c'est-à-dire trier par taille, supprimer quelques fichiers volumineux inutiles

réponse donnée Sergey 13.09.2011 - 13:25
la source
1

EDIT: Je suppose que ce message n’est pas "pas particulièrement utile" comme je le pensais. C'est une solution très rapide qui ne fait que garder trace du dernier fichier modifié (au lieu de trier la liste complète des fichiers):

find . -type f -printf '%[email protected] %p\n' | awk 'BEGIN { mostrecenttime = 0; mostrecentline = "nothing"; } { if ($1 > mostrecenttime) { mostrecenttime = $1; mostrecentline = $0; } } END { print mostrecentline; }' | cut -f2- -d ' '

Réparti sur plusieurs lignes pour plus de clarté, il se présente comme suit:

find . -type f -printf '%[email protected] %p\n' | awk '
    BEGIN { mostrecenttime = 0; mostrecentline = "nothing"; }
    {
        if ($1 > mostrecenttime)
            { mostrecenttime = $1; mostrecentline = $0; }
    }
    END { print mostrecentline; }' | cut -f2- -d ' '

Fin de modification

Ce message n’est pas particulièrement utile, mais comme "organiser" parlait de rapidité, je pensais partager cela.

Les solutions de

arrange et de enzotib impliquent de lister tous les fichiers du répertoire avec leurs heures, puis de les trier. Comme vous le savez, le tri n’est pas nécessaire pour trouver le maximum. Trouver le maximum peut être fait en temps linéaire mais le tri prend n log (n) temps [Je sais que la différence n’est pas grande, mais quand même;)]. Je ne peux pas penser à un moyen élégant de mettre cela en œuvre. [EDIT: Une mise en œuvre soignée (bien que sale) et rapide fournie ci-dessus.]

Meilleure chose à faire: pour rechercher le dernier fichier modifié dans un répertoire, recherchez de manière récursive le dernier fichier modifié dans chaque sous-répertoire de niveau 1. Laissez ce fichier représenter le sous-répertoire. Maintenant, triez les fichiers de niveau 1 avec les représentants des sous-répertoires de niveau 1. Si le nombre de fichiers de niveau 1 et de sous-répertoires de chaque répertoire est presque constant, le processus doit évoluer de manière linéaire avec le nombre total de fichiers.

C’est ce que j’ai proposé de mettre en œuvre ceci:

findrecent() { { find "$1" -maxdepth 1 -type f -exec stat -c "%y %n" {} + | sort -r | head -1 && find "$1" -mindepth 1 -maxdepth 1 -type d -exec findrecent {} \;; } | sort -r | head -1; }
findrecent .

J'ai exécuté ceci et j'ai eu un tas d'erreurs find: findrecent: No such file or directory . Raison: -exec de la recherche s'exécute dans un shell différent. J'ai essayé de définir findrecent dans .bashrc, .xsessionrc mais cela n'a pas aidé [j'apprécierais l'aide ici]. En fin de compte, j'ai eu recours à

#!/bin/bash
{ find "$1" -maxdepth 1 -type f -exec stat -c "%y %n" {} + | sort -r | head -1 && find "$1" -mindepth 1 -maxdepth 1 -type d -exec findrecent {} \;; } | sort -r | head -1;

dans un script appelé findrecent dans mon CHEMIN, puis en l'exécutant.

J'ai couru ça, je continuais d'attendre et d'attendre sans sortie. Juste pour m'assurer que je n'avais pas affaire à des boucles infinies, j'ai modifié le fichier en

#!/bin/bash
echo "$1" >&2
{ find "$1" -maxdepth 1 -type f -exec stat -c "%y %n" {} + | sort -r | head -1 && find "$1" -mindepth 1 -maxdepth 1 -type d -exec findrecent {} \;; } | sort -r | head -1;

et réessayé. Cela a fonctionné - mais cela a pris 1 minute 35 secondes sur mon homefolder - les solutions d’arrangement et d’enzotib ont pris respectivement 1,69 et 1,95 secondes!

Voilà pour la supériorité de O (n) sur O (n log (n))! Bon sang, vous appelez des frais généraux! [Ou plutôt la surcharge d'appel de script]

Mais ce script s'adapte mieux que les solutions précédentes et je parie qu'il s'exécutera plus rapidement que sur la banque de mémoire de Google; D

    
réponse donnée S Prasanth 11.12.2012 - 13:51
la source
1

Utilisez perl en conjonctin avec find :

 find my_directory -type f -printf '%[email protected]\t%p\n' | perl -ane '@[email protected] if ($F[0]>$m[0]); END{print $m[1];}'

Vous obtenez le nom du fichier avec la plus grande époque == dernier fichier modifié.

    
réponse donnée MUY Belgium 10.03.2015 - 12:08
la source

Lire d'autres questions sur les étiquettes