Je cherche un one-liner Shell pour trouver le fichier le plus ancien dans une arborescence de répertoires.
Cela fonctionne (mis à jour pour intégrer la suggestion de Daniel Andersson):
find -type f -printf '%T+ %p\n' | sort | head -n 1
Celui-ci est un peu plus portable et, comme il ne repose pas sur le GNU find
extension -printf
, il fonctionne donc également sous BSD/OS X:
find . -type f -print0 | xargs -0 ls -ltr | head -n 1
Le seul inconvénient est qu’il est quelque peu limité à la taille de ARG_MAX
(qui devrait n’est pas pertinent pour la plupart des nouveaux noyaux). Ainsi, s'il y a plus de getconf ARG_MAX
caractères renvoyés (262 144 sur mon système), le résultat n'est pas correct. Ce n'est pas non plus compatible POSIX car -print0
et xargs -0
ne le sont pas.
Quelques solutions supplémentaires à ce problème sont décrites ici: Comment puis-je trouver le fichier le plus récent (le plus récent, le plus ancien, le plus ancien) dans un répertoire? - Wiki de Greg
Les commandes suivantes sont garanties pour fonctionner avec tout type de nom de fichier étrange:
find -type f -printf "%T+ %p\0" | sort -z | grep -zom 1 ".*" | cat
find -type f -printf "%T@ %T+ %p\0" | \
sort -nz | grep -zom 1 ".*" | sed 's/[^ ]* //'
stat -c "%y %n" "$(find -type f -printf "%T@ %p\0" | \
sort -nz | grep -zom 1 ".*" | sed 's/[^ ]* //')"
L'utilisation d'un octet nul (\0
) au lieu d'un caractère de saut de ligne (\n
) garantit que la sortie de find sera toujours compréhensible au cas où l'un des noms de fichier contiendrait un caractère de saut de ligne.
Le commutateur -z
permet à la fois à sort et à grep d'interpréter uniquement les octets nuls en tant que caractères de fin de ligne. Comme il n’existe pas de commutateur de ce type pour head, nous utilisons plutôt grep -m 1
(une seule occurrence).
Les commandes sont classées par heure d'exécution (mesurée sur ma machine).
La première commande sera la plus lente car elle doit d'abord convertir chaque fichier mtime en un format lisible par l'homme, puis trier ces chaînes. Piping to Cat évite de colorer la sortie.
La deuxième commande est légèrement plus rapide. Tandis qu'il effectue toujours la conversion de date, le tri numérique (sort -n
) des secondes écoulées depuis qu'Unix Epoch est un peu plus rapide. sed supprime les secondes depuis Unix Epoch.
La dernière commande ne fait aucune conversion et devrait être nettement plus rapide que les deux premières. La commande de recherche elle-même n’affiche pas l’heure mtime du fichier le plus ancien. Par conséquent, stat est nécessaire.
Pages de manuel connexes: trouver - grep - sed - trier - stat
Bien que la réponse acceptée et d’autres ici fonctionnent, si vous avez un très grand arbre, ils trieront l’ensemble des fichiers.
Ce serait mieux si nous pouvions simplement les énumérer et garder une trace des plus anciens, sans qu'il soit nécessaire de les trier.
C'est pourquoi j'ai proposé cette solution alternative:
ls -lRU $PWD/* | awk 'BEGIN {cont=0; oldd=strftime("%Y%m%d"); } { gsub(/-/,"",$6); if (substr($1,0,1)=="/") { pat=substr($1,0,length($0)-1)"/"; }; if( $6 != "") {if ( $6 < oldd ) { oldd=$6; oldf=pat$8; }; print $6, pat$8; count++;}} END { print "Oldest date: ", oldd, "\nFile:", oldf, "\nTotal compared: ", count}'
J'espère que cela pourra vous aider, même si la question est un peu ancienne.
Éditer 1: ces modifications permettent d'analyser des fichiers et des répertoires avec des espaces. Il est assez rapide pour le publier à la racine /
et trouver le fichier le plus ancien jamais créé.
ls -lRU --time-style=long-iso "$PWD"/* | awk 'BEGIN {cont=0; oldd=strftime("%Y%m%d"); } { gsub(/-/,"",$6); if (substr($0,0,1)=="/") { pat=substr($0,0,length($0)-1)"/"; $6="" }; if( $6 ~ /^[0-9]+$/) {if ( $6 < oldd ) { oldd=$6; oldf=$8; for(i=9; i<=NF; i++) oldf=oldf $i; oldf=pat oldf; }; count++;}} END { print "Oldest date: ", oldd, "\nFile:", oldf, "\nTotal compared: ", count}'
Commande expliquée:
Le lancer:
~ $ time ls -lRU "$ PWD"/* | awk etc.
Date la plus ancienne: 19691231
Fichier: /home/.../.../backupold/.../EXAMPLES/how-to-program.txt
Total comparé: 111438
real 0m1.135s
utilisateur 0m0.872s
sys 0m0.760s
EDIT 2: Même concept, meilleure solution en utilisant find
pour regarder le heure d'accès (utilisez %T
avec la première printf
pour heure de modification ou %C
pour changement d'état à la place).
find . -wholename "*" -type f -printf "%AY%Am%Ad %h/%f\n" | awk 'BEGIN {cont=0; oldd=strftime("%Y%m%d"); } { if ($1 < oldd) { oldd=$1; oldf=$2; for(i=3; i<=NF; i++) oldf=oldf " " $i; }; count++; } END { print "Oldest date: ", oldd, "\nFile:", oldf, "\nTotal compared: ", count}'
EDIT 3: La commande ci-dessous utilise heure de modification et affiche également la progression incrémentielle lorsqu’elle trouve des fichiers de plus en plus anciens, ce qui est utile lorsque vous avez des horodatages incorrects (comme le 19.01.1990):
find . -wholename "*" -type f -printf "%TY%Tm%Td %h/%f\n" | awk 'BEGIN {cont=0; oldd=strftime("%Y%m%d"); } { if ($1 < oldd) { oldd=$1; oldf=$2; for(i=3; i<=NF; i++) oldf=oldf " " $i; print oldd " " oldf; }; count++; } END { print "Oldest date: ", oldd, "\nFile:", oldf, "\nTotal compared: ", count}'
Veuillez utiliser ls - la page de manuel vous explique comment commander le répertoire.
ls -clt | head -n 2
Le -n 2 est tel que vous n'obtenez pas le "total" dans la sortie. Si vous voulez seulement le nom du fichier.
ls -t | head -n 1
Et si vous avez besoin de la liste dans l’ordre normal (obtenir le fichier le plus récent)
ls -tr | head -n 1
Beaucoup plus facile que d’utiliser find, beaucoup plus rapide et plus robuste - n’ayez pas à vous soucier des formats de nommage des fichiers. Cela devrait également fonctionner sur presque tous les systèmes.
find ! -type d -printf "%T@ %p\n" | sort -n | head -n1
Il semble que par "plus ancien", la plupart des gens ont supposé que vous entendiez par "temps de modification le plus ancien". C'est probablement corrigé, selon l'interprétation la plus stricte de "plus ancien", mais si vous vouliez celle avec le plus ancien accès heure, je modifierais la meilleure réponse ainsi:
find -type f -printf '%A+ %p\n' | sort | head -n 1
Notez le %A+
.