Comment lister les fichiers triés par date de modification de manière récursive (aucune commande stat disponible!)

31

Comment puis-je obtenir la liste de tous les fichiers dans le répertoire actuel avec leur date de modification et triés par cette date?

Maintenant, je sais comment y parvenir avec find, statet sort, mais pour une raison étrange, le statn'est pas installé sur la boîte et il est peu probable que je puisse le faire installer.

Une autre option?

PS: gccn'est pas installé non plus

alex
la source
Pouvez-vous télécharger un binaire compilé et l'exécuter là-bas?
imz - Ivan Zakharyaschev
@imz: oui, c'est une autre façon de procéder. L' find -printfaction semble cependant être la plus simple.
alex

Réponses:

27

Ma méthode la plus courte utilise zsh:

print -rl -- **/*(.Om)

(ajoutez les Dqualificatifs glob si vous souhaitez également lister les fichiers cachés ou les fichiers dans des répertoires cachés).

Si vous avez GNU find, faites-le imprimer les heures de modification du fichier et triez-les. Je suppose qu'il n'y a pas de nouvelle ligne dans les noms de fichiers.

find . -type f -printf '%T@ %p\n' | sort -k 1 -n | sed 's/^[^ ]* //'

Si vous avez Perl (encore une fois, en supposant qu'il n'y ait pas de nouvelle ligne dans les noms de fichiers):

find . -type f -print |
perl -l -ne '
    $_{$_} = -M;  # store file age (mtime - now)
    END {
        $,="\n";
        print sort {$_{$b} <=> $_{$a}} keys %_;  # print by decreasing age
    }'

Si vous avez Python (encore une fois, en supposant qu'il n'y ait pas de nouvelle ligne dans les noms de fichiers):

find . -type f -print |
python -c 'import os, sys; times = {}
for f in sys.stdin.readlines(): f = f[0:-1]; times[f] = os.stat(f).st_mtime
for f in sorted(times.iterkeys(), key=lambda f:times[f]): print f'

Si vous avez un accès SSH à ce serveur, montez le répertoire sur sshfs sur une machine mieux équipée:

mkdir mnt
sshfs server:/path/to/directory mnt
zsh -c 'cd mnt && print -rl **/*(.Om)'
fusermount -u mnt

Avec seulement les outils POSIX, c'est beaucoup plus compliqué, car il n'y a pas de bon moyen de trouver l'heure de modification d'un fichier. La seule façon standard de récupérer les heures d'un fichier estls et le format de sortie dépend des paramètres régionaux et est difficile à analyser.

Si vous pouvez écrire dans les fichiers et que vous ne vous souciez que des fichiers normaux et qu'il n'y a pas de nouvelle ligne dans les noms de fichiers, voici un horrible problème: créez des liens durs vers tous les fichiers dans un seul répertoire et triez-les par heure de modification.

set -ef                       # disable globbing
IFS='
'                             # split $(foo) only at newlines
set -- $(find . -type f)      # set positional arguments to the file names
mkdir links.tmp
cd links.tmp
i=0 list=
for f; do                     # hard link the files to links.tmp/0, links.tmp/1, …
  ln "../$f" $i
  i=$(($i+1))
done
set +f
for f in $(ls -t [0-9]*); do  # for each file, in reverse mtime order:
  eval 'list="${'$i'}         # prepend the file name to $list
$list"'
done
printf %s "$list"             # print the output
rm -f [0-9]*                  # clean up
cd ..
rmdir links.tmp
Gilles, arrête de faire le mal
la source
Le moyen le plus simple est probablement find . -print | xargs -n99999 -s999999 ls -ltr. Mais cela a le problème que (1) xargspeut ne pas autoriser -mplus de 512 ou -splus de 5120, et (b) même si vous pouvez contourner cela, il y a toujours une taille maximale imposée par le noyau de la liste d'arguments et de l'environnement combinés. La plupart de vos idées (sauf celles de Perl et Python) ont le même problème, c'est pourquoi j'ai spécifiquement évité de construire de longues lignes de commande.
geekosaur
En particulier, j'obtiens régulièrement des erreurs de "liste d'arguments trop longue" en utilisant zshdes globs récursifs dans le cas général.
geekosaur
@geekosaur: Seul le dernier horrible kludge a un problème avec les longues lignes de commande. Dans zsh, vous pouvez faire beaucoup avec les intégrés (par exemple, print -rl **/*la seule limite est la quantité de mémoire libre dont vous disposez), et au-delà zargs. Votre proposition de find … | xargs … lstriera correctement si xargsfinit par être invoquée lsune seule fois et ne fonctionnera pas s'il y a des caractères spéciaux dans les noms de fichiers.
Gilles 'SO- arrête d'être méchant'
merci beaucoup pour la réponse extrêmement détaillée avec beaucoup d'options! :)
alex
Et c'est pourquoi j'aime zsh.
Profpatsch
14

En supposant GNU find:

find . -printf '%T@ %c %p\n' | sort -k 1n,1 -k 7 | cut -d' ' -f2-

Changer 1n,1en1nr,1 si vous voulez que les fichiers listés plus récents.

Si vous n'avez pas GNU, findcela devient plus difficile car lsle format d'horodatage varie énormément (les fichiers récemment modifiés ont un style d'horodatage différent, par exemple).

geekosaur
la source
En fait, vous pouvez également modifier le format de la date et de l'heure avec ls --time-style="..."- je ne sais pas s'il s'agit de ls standard ou GNU, probablement GNU.
asoundmove
Certainement GNU.
geekosaur
@asoundmove: malheureusement, la boîte est trop ancienne (RedHat 7.2) et lsn'a pas cette option.
alex
7

Sur un Mac, il n'y a pas d'argument -printf à trouver, mais vous pouvez le faire à la place:

find . -print0 | xargs -0 -n 100 stat -f"%m %Sm %N" | sort -n|awk '{$1="";print}'

killdash9
la source
0

on peut essayer cela (il faut quand même le construire soi-même) https://github.com/shadkam/recentmost

user3392225
la source
6
Bienvenue sur Unix et Linux Stack Exchange! Bien que cela puisse théoriquement répondre à la question, il serait préférable d’inclure ici les parties essentielles de la réponse et de fournir le lien à titre de référence.
slm
0

Ignorer les fichiers cachés - avec un horodatage agréable et rapide

Gère bien les espaces dans les noms de fichiers - pas que vous devez les utiliser!

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

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 à findgogo peut être trouvé en suivant le lien.

Serge Stroobandt
la source
0

En parlant généralement de trouver des fichiers par date (cela ne fonctionnera pas pour l'affiche originale, mais je me suis retrouvé ici, donc j'ai pensé que d'autres pourraient aussi bien). Dans mon cas d'utilisation, je souhaite répertorier les fichiers dans le but de les examiner avant leur suppression.

Avec findutils 4.6.0 j'aime:

find . -type f -mtime +270 -exec ls -laFGht --time-style=iso {} \+

La commande ci - dessus trouve des fichiers ( -type f), dans le répertoire de travail ( .il y a qui ont été modifiés) plus de 270 jours ( -mtime +270également -mtime 0produira les dernières 24 heures, et -mtime -5montre les 5 derniers jours). Il les utilise ensuite lspour les répertorier par date, le plus récent en premier (-exec ls -laFGht --time-style=iso {} \+ )

Voici un échantillon de la sortie:

-rwxrwx---+ 1 user1 208M 2018-07-16  ./filename.bak*
-rwxrwx---+ 1 user1  702 2018-07-15  ./filename.ldf*
-rwxrwx---+ 1 user1 208M 2018-07-15  ./filename.bak*

La grande chose à ce sujet est qu'une fois la liste révisée, il est simple de remplacer la partie liste par la findcommande delete:

find . -type f -mtime +270 -delete
Steph
la source