Il semble que ls
ne trie pas les fichiers correctement lors d’un appel récursif:
ls -altR . | head -n 3
Comment trouver le dernier fichier modifié dans un répertoire (y compris les sous-répertoires)?
find . -type f -printf '%T@ %p\n' | sort -n | tail -1 | cut -f2- -d" "
Pour un arbre énorme, il peut être difficile pour sort
de tout garder en mémoire.
%T@
vous donne l'heure de modification comme un horodatage unix, sort -n
trie numériquement, tail -1
prend la dernière ligne (horodatage le plus élevé), cut -f2 -d" "
coupe le premier champ (l'horodatage) de la sortie.
Edit: Tout comme -printf
est probablement uniquement GNU, l'utilisation ajreals de stat -c
l'est aussi. Bien qu'il soit possible de faire la même chose sous BSD, les options de formatage sont différentes (-f "%m %N"
semble-t-il)
Et j'ai raté le pluriel; si vous voulez plus que le dernier fichier, augmentez simplement l'argument tail.
Pour faire suite à @ plundra , voici la version BSD et OS X:
find . -type f -print0 | xargs -0 stat -f "%m %N" |
sort -rn | head -1 | cut -f2- -d" "
Au lieu de trier les résultats et de ne conserver que les derniers modifiés, vous pouvez utiliser awk pour n’imprimer que celui dont le temps de modification est le plus élevé (en temps unix):
find . -type f -printf "%T@\0%p\0" | awk '
{
if ($0>max) {
max=$0;
getline mostrecent
} else
getline
}
END{print mostrecent}' RS='\0'
Cela devrait être un moyen plus rapide de résoudre votre problème si le nombre de fichiers est suffisant.
J'ai utilisé le caractère NUL (c'est-à-dire '\ 0') car, théoriquement, un nom de fichier peut contenir n'importe quel caractère (y compris l'espace et la nouvelle ligne), à l'exception de cela.
Si vous n'avez pas de tels noms de fichiers pathologiques dans votre système, vous pouvez également utiliser le caractère de nouvelle ligne:
find . -type f -printf "%T@\n%p\n" | awk '
{
if ($0>max) {
max=$0;
getline mostrecent
} else
getline
}
END{print mostrecent}' RS='\n'
De plus, cela fonctionne aussi dans mawk.
J'ai eu du mal à trouver le dernier fichier modifié sous Solaris 10. Il n'y a pas d'option find
et l'option printf
et stat
ne sont pas disponibles. J'ai découvert la solution suivante qui fonctionne bien pour moi:
find . -type f | sed 's/.*/"&"/' | xargs ls -E | awk '{ print $6," ",$7 }' | sort | tail -1
Pour afficher également le nom du fichier, utilisez
find . -type f | sed 's/.*/"&"/' | xargs ls -E | awk '{ print $6," ",$7," ",$9 }' | sort | tail -1
Explication
find . -type f
trouve et répertorie tous les fichierssed 's/.*/"&"/'
encapsule le chemin d'accès entre guillemets pour gérer les espacesxargs ls -E
envoie le chemin cité à ls
, l'option -E
s'assure qu'un horodatage complet (format année-mois-jour heure-minute-secondes-nanosecondes) est renvoyéawk '{ print $6," ",$7 }'
extrait uniquement la date et l'heureawk '{ print $6," ",$7," ",$9 }'
extrait la date, l'heure et le nom du fichiersort
renvoie les fichiers triés par datetail -1
renvoie uniquement le dernier fichier modifiéCela semble bien fonctionner, même avec les sous-répertoires:
find . -type f | xargs ls -ltr | tail -n 1
En cas de trop grand nombre de fichiers, affinez la recherche.
Affiche le dernier fichier avec un horodatage lisible par l'homme:
find . -type f -printf '%TY-%Tm-%Td %TH:%TM: %Tz %p\n'| sort -n | tail -n1
Le résultat ressemble à ceci:
2015-10-06 11:30: +0200 ./foo/bar.txt
Pour afficher plus de fichiers, remplacez -n1
par un nombre plus élevé.
Cela donne une liste triée:
find . -type f -ls 2>/dev/null | sort -M -k8,10 | head -n5
Inverser la commande en plaçant un '-r' dans la commande de tri. Si vous ne voulez que les noms de fichiers, insérez "awk '{print $ 11}' |" avant '| tête'
Sous Ubuntu 13, ce qui suit fonctionne, peut-être un peu plus vite, car il inverse le tri et utilise "tête" au lieu de "queue", ce qui réduit le travail. Pour afficher les 11 fichiers les plus récents dans un arbre:
trouver . -type f -printf '% T @% p\n' | trier -n -r | tête -11 | cut -f2- -d "" | sed -e 's, ^./,' | xargs ls -U -l
Cela donne une liste complète de ls sans re-trier et omet le './' ennuyeux que 'trouver' met sur chaque nom de fichier.
Ou, en tant que fonction 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
}
Néanmoins, la plupart du travail a été effectué avec la solution initiale de plundra. Merci beaucoup.
Si exécuter stat
sur chaque fichier individuellement est lent, vous pouvez utiliser xargs
pour accélérer un peu les choses:
find . -type f -print0 | xargs -0 stat -f "%m %N" | sort -n | tail -1 | cut -f2- -d" "
Cela modifie de manière récursive l'heure de modification de tous les répertoires du répertoire actuel vers le fichier le plus récent de chaque répertoire
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
J'utilise quelque chose de similaire tout le temps, ainsi que la liste des plus récents fichiers modifiés. Pour les grandes arborescences de répertoires, il peut être beaucoup plus rapide pour éviter le tri. Dans le cas du dernier fichier modifié le plus récent:
find . -type f -printf '%T@ %p\n' | Perl -ne '@a=split(/\s+/, $_, 2); ($t,$f)=@a if $a[0]>$t; print $f if eof()'
Sur un répertoire contenant 1,7 million de fichiers, j'obtiens le dernier en 3.4, soit 7,5 fois plus rapide que la solution 25.5 avec tri.
J'ai fait face au même problème. Je dois trouver le fichier le plus récent de manière récursive. Il a fallu environ 50 minutes pour trouver.
Voici un petit script pour le faire plus vite:
#!/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
C'est une fonction récursive qui récupère l'élément modifié le plus récent d'un répertoire. Si cet élément est un répertoire, la fonction est appelée de manière récursive et recherche dans ce répertoire, etc.
Ce simple cli fonctionnera également:
ls -1t | head -1
Vous pouvez changer le -1 pour le nombre de fichiers que vous voulez lister
La commande suivante a fonctionné sous Solaris:
find . -name "*Zip" -type f | xargs ls -ltr | tail -1
Je trouve ce qui suit plus court et avec une sortie plus interprétable:
find . -type f -printf '%TF %TT %p\n' | sort | tail -1
Étant donné la longueur fixe des dates-temps au format ISO normalisé, le tri lexicographique convient et nous n'avons pas besoin de l'option -n
pour le tri.
Si vous souhaitez supprimer à nouveau les horodatages, vous pouvez utiliser:
find . -type f -printf '%TFT%TT %p\n' | sort | tail -1 | cut -f2- -d' '
Pour rechercher des fichiers dans/target_directory et tous ses sous-répertoires modifiés au cours des 60 dernières minutes:
$ find /target_directory -type f -mmin -60
Pour rechercher les derniers fichiers modifiés, triés dans l’ordre inverse de la date de mise à jour (c’est-à-dire les fichiers les plus récemment mis à jour en premier):
$ find /etc -type f -printf '%TY-%Tm-%Td %TT %p\n' | sort -r
$ find . -type f -not -path '*/\.*' -printf '%TY.%Tm.%Td %THh%TM %Ta %p\n' |sort -nr |head -n 10
Gère bien les espaces dans les noms de fichiers - pas que ceux-ci doivent être utilisés!
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
Plusfind
à gogo en suivant le lien.
J'ai trouvé la commande ci-dessus utile, mais pour mon cas, j'avais besoin de connaître la date et l'heure du fichier. Un problème avec plusieurs fichiers contenant des espaces dans les noms .
find . -type f -printf '%T@ %p\n' | sort -n | tail -1 | cut -f2- -d" " | sed 's/.*/"&"/' | xargs ls -l
J'ai écrit un paquet pypi/github pour cette question car j'avais également besoin d'une solution.
https://github.com/bucknerns/logtail
Installer:
pip install logtail
Usage: fichiers modifiés
logtail <log dir> [<glob match: default=*.log>]
Usage2: Ouvre le dernier fichier modifié dans l'éditeur
editlatest <log dir> [<glob match: default=*.log>]
Je préfère celui-ci, il est plus court:
find . -type f -print0|xargs -0 ls -drt|tail -n 1