Il semble que ls
ne trie pas correctement les fichiers lors d'un appel récursif:
ls -altR . | head -n 3
Comment puis-je trouver le fichier modifié le plus récemment dans un répertoire (y compris les sous-répertoires)?
Il semble que ls
ne trie pas correctement les fichiers lors d'un appel récursif:
ls -altR . | head -n 3
Comment puis-je trouver le fichier modifié le plus récemment dans un répertoire (y compris les sous-répertoires)?
Réponses:
find . -type f -printf '%T@ %p\n' | sort -n | tail -1 | cut -f2- -d" "
Pour un arbre énorme, il peut être difficile de sort
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
probablement uniquement GNU, l'utilisation correcte de l' stat -c
est également. Bien qu'il soit possible de faire de même sur BSD, les options de formatage sont différentes ( -f "%m %N"
il semblerait)
Et j'ai raté la partie du pluriel; si vous voulez plus que le dernier fichier, augmentez simplement l'argument tail.
sort -rn | head -3
au lieu de sort -n | tail -3
. Une version donne les fichiers du plus ancien au plus récent, tandis que l'autre va du plus récent au plus ancien.
sort
va créer des fichiers temporaires (in /tmp
) au besoin, donc je ne pense pas que ce soit un problème.
-printf '%T@ %Tb %Td %TY %p\n'
vous donnera un horodatage (si nécessaire) (similaire à ls
)
find . -type f -printf '%TF %TT %p\n' | sort | tail -1
Suite à la réponse de @ 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" "
find
charge +
au lieu de \;
? Parce que cela fait la même chose (passer plusieurs fichiers en tant que paramètres), sans le -print0 | xargs -0
tube.
head -1
àhead -5
Au lieu de trier les résultats et de ne conserver que les derniers modifiés, vous pouvez utiliser awk pour imprimer uniquement celui avec le plus grand temps de modification (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 suffisamment important.
J'ai utilisé le caractère NUL (c'est-à-dire '\ 0') parce que, théoriquement, un nom de fichier peut contenir n'importe quel caractère (y compris l'espace et la nouvelle ligne) mais 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.
mawk
l'alternative standard Debian.
J'ai eu du mal à trouver le dernier fichier modifié sous Solaris 10. Il find
n'y a pas d' printf
option et stat
n'est pas disponible. 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 de fichier
find . -type f | sed 's/.*/"&"/' | xargs ls -E | awk '{ print $6," ",$7," ",$9 }' | sort | tail -1
Explication
find . -type f
recherche et répertorie tous les fichierssed 's/.*/"&"/'
encapsule le chemin entre guillemets pour gérer les espaces blancsxargs ls -E
envoie le chemin entre guillemets à ls
, l' -E
option s'assure qu'un horodatage complet (format année-mois-jour heure-minute-secondes-nanosecondes ) est retourné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 fonctionner correctement, même avec des sous-répertoires:
find . -type f | xargs ls -ltr | tail -n 1
En cas de trop de fichiers, affinez la recherche.
-l
option ls
semble inutile. -tr
Semble juste suffisant.
find . -type f -print0 | xargs -0 ls -ltr | tail -n 1
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-les -n1
par un nombre plus élevé
J'utilise quelque chose de similaire tout le temps, ainsi que la liste top-k des fichiers les plus récemment modifiés. Pour les grandes arborescences de répertoires, il peut être beaucoup plus rapide d'éviter le tri . Dans le cas du premier fichier modifié en dernier lieu:
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 plus récent en 3,4s, une accélération de 7,5x contre la solution de 25,5s en utilisant sort.
lastfile
) et vous pouvez ensuite faire ce que vous voulez avec le résultat, comme ls -l $(lastfile .)
, ou open $(lastfile .)
(sur un Mac), etc.
Sur Ubuntu 13, ce qui suit le fait, peut-être un peu plus vite, car il inverse le tri et utilise 'head' au lieu de 'tail', ce qui réduit le travail. Pour afficher les 11 fichiers les plus récents dans une arborescence:
trouver . -type f -printf '% T @% p \ n' | sort -n -r | tête -11 | cut -f2- -d "" | sed -e, ^. / ,, '| xargs ls -U -l
Cela donne une liste complète de ls sans re-tri et omet l'ennuyeux './' que 'find' 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
}
Pourtant, la plupart du travail a été fait par la solution originale de plundra. Merci plundra.
J'ai fait face au même problème. J'ai besoin de trouver le fichier le plus récent de manière récursive. trouver a pris environ 50 minutes pour trouver.
Voici un petit script pour le faire plus rapidement:
#!/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
Il s'agit d'une fonction récursive qui obtient 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 récursivement et recherche dans ce répertoire, etc.
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
Compte tenu de la longueur fixe des heures de format standard ISO, le tri lexicographique est très bien et nous n'avons pas besoin de l' -n
option sur 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' '
Si l'exécution stat
sur chaque fichier individuellement est trop lente, 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 récursivement l'heure de modification de tous les répertoires du répertoire actuel par 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
Ce simple cli fonctionnera également:
ls -1t | head -1
Vous pouvez changer le -1 au nombre de fichiers que vous souhaitez lister
J'ai trouvé la commande ci-dessus utile, mais pour mon cas, j'avais besoin de voir la date et l'heure du fichier et j'ai eu un problème avec plusieurs fichiers qui ont des espaces dans les noms. Voici ma solution de travail.
find . -type f -printf '%T@ %p\n' | sort -n | tail -1 | cut -f2- -d" " | sed 's/.*/"&"/' | xargs ls -l
$ 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
Plus à find
gogo en suivant le lien.
Pour rechercher des fichiers dans / target_directory et tous ses sous-répertoires, qui ont été modifiés au cours des 60 dernières minutes:
$ find /target_directory -type f -mmin -60
Pour rechercher les fichiers les plus récemment modifiés, triés dans l'ordre inverse de l'heure 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
Je préfère celui-ci, il est plus court:
find . -type f -print0|xargs -0 ls -drt|tail -n 1
J'ai écrit un package pypi / github pour cette question car j'avais également besoin d'une solution.
https://github.com/bucknerns/logtail
Installer:
pip install logtail
Utilisation: queues 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>]