223 votes

Unix/Linux rechercher et trier par date de modification

Comment puis-je faire un simple find qui ordonnerait les résultats par ordre de modification la plus récente ?

Voici l'actuel find J'utilise (je fais un Shell escape en PHP, c'est donc le raisonnement pour les variables) :

find '$dir' -name '$str'\* -print | head -10

Comment puis-je faire en sorte que la recherche soit ordonnée en fonction des dernières modifications ? (Notez que je ne veux pas que le tri se fasse "après" la recherche, mais plutôt que les résultats soient classés en fonction des dernières modifications).

0 votes

github.com/shadkam/recentmost ferait ce que l'on souhaite, mais il faut le construire.

274voto

user195696 Points 2681

Utilisez ça :

find . -printf "%T@ %Tc %p\n" | sort -n

printf Les arguments de man find :

  • %Tk : L'heure de dernière modification du fichier dans le format spécifié par k .

  • @ : secondes depuis le 1er janvier 1970, 00:00 GMT, avec partie fractionnaire.

  • c : date et heure de la locale (Sat Nov 04 12:02:33 EST 1989).

  • %p : Nom du fichier.

11 votes

+1 Très utile, la première réponse à ce problème que j'ai trouvée avec une sortie de date lisible/utile.

0 votes

Le plus fiable (et très simple) puisque le temps est accordé pour être numériquement séquentiel (donc toujours correctement triable), thx !

2 votes

J'ai cet alias pour trouver les fichiers récents dans mon ~/.zshrc : fr () { find ./ -iname "*"$@"*" -printf "%T@ %Td-%Tb-%TY %Tk:%TM %p\n" | sort -n | cut -d " " -f 2- | grep -i "$@" ; } Elle trouve récursivement tous les fichiers contenant le motif du premier argument passé à la commande ( fr <pattern> ) et les trie avec le plus récent en dernier.

91voto

La méthode la plus facile est d'utiliser zsh, grâce à son qualificatifs globaux .

print -lr -- $dir/**/$str*(om[1,10])

Si vous avez GNU find, faites-lui imprimer les temps de modification des fichiers et triez-les par là.

find -type f -printf '%T@ %p\0' |
sort -zk 1nr |
sed -z 's/^[^ ]* //' | tr '\0' '\n' | head -n 10

Si vous avez GNU find mais pas d'autres utilitaires GNU, utilisez des nouvelles lignes comme séparateurs au lieu de nulles ; vous perdrez le support des noms de fichiers contenant des nouvelles lignes.

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

Si vous avez Perl (ici je supposerai qu'il n'y a pas de nouvelles lignes dans les noms de fichiers) :

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

Si vous avez Python (en supposant également qu'il n'y a pas de nouvelles lignes 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], reverse=True))[:10]: print f'

Il y a probablement un moyen de faire la même chose en PHP, mais je ne le connais pas.

Si vous voulez travailler uniquement avec des outils POSIX, c'est un peu plus compliqué ; voir Comment lister les fichiers triés par date de modification de manière récursive (aucune commande stat disponible !) (Retraiter les 10 premiers est la partie facile).

0 votes

Je pense que le find montre les fichiers les plus anciens, et que vous devez ajouter l'option -r option pour sort .

0 votes

Mon sed dit qu'il n'a pas d'option -z.

1 votes

@KefSchecter Utilisez alors les retours à la ligne comme séparateurs, mais vous perdrez la prise en charge des retours à la ligne dans les noms de fichiers.

54voto

Vous n'avez pas besoin de connaître PHP ou Python, il suffit de ls :

man ls:
-t     sort by modification time
-r,    reverse order while sorting (--reverse )
-1     list one file per line

find /wherever/your/files/hide -type f -exec ls -1rt "{}" +;

Si la commande * sort avec un état d'échec (c'est-à-dire Liste d'arguments trop longue ), alors vous pouvez itérer avec find. Paraphrase de : La longueur maximale des arguments pour un nouveau processus

  • find . -print0|xargs -0 command (optimise la vitesse, si find n'implémente pas "-exec +" mais connaît "-print0")
  • find . -print|xargs command (s'il n'y a pas d'espace blanc dans les arguments)

Si la majeure partie des arguments consiste en des chemins longs, absolus ou relatifs, essayez de déplacer vos actions dans le répertoire : cd /directory/with/long/path; command * Et une autre solution rapide pourrait être de faire correspondre moins d'arguments : command [a-e]*; command [f-m]*; ...

2 votes

S'il y a beaucoup de fichiers, cela échoue avec 'Argument list too long' sur le ls.

1 votes

C'est vrai, mais je crois que la question était "comment faire une simple recherche...".

2 votes

Ls ne cite pas les noms de fichiers d'une manière que xargs peut comprendre (pas d'option -0, et les différents styles de citation sont inadéquats)

16voto

Evgeni Sergeev Points 1735

Extension du site La réponse de l'utilisateur195696 :

find . -type f -printf "%T@\t%Tc %6k KiB %p\n" | sort -n | cut -f 2-

Pour chaque fichier, cela produit d'abord l'horodatage numérique (pour le tri), suivi de la tabulation. \t ), puis un horodatage lisible par un humain, puis la taille des fichiers (malheureusement find 's -printf ne peut pas faire en mebibytes, seulement en kibytes), puis le nom du fichier avec le chemin relatif.

Puis sort -n le trie par le premier champ numérique.

Puis cut se débarrasse du premier champ numérique qui n'est d'aucun intérêt pour l'utilisateur. (Imprime le deuxième champ et les suivants.) Le séparateur de champ par défaut est \t ou la tabulation.

Exemple de sortie :

Thu 06 Feb 2014 04:49:14 PM EST     64 KiB ./057_h2_f7_10/h2_f7_10.class
Fri 07 Feb 2014 02:08:30 AM EST 7962976 KiB ./056_h2_f7_400/h2__rh_4e-4.mph
Fri 07 Feb 2014 02:23:24 AM EST 7962976 KiB ./056_h2_f7_400/h2_f7_400_out_Model.mph
Fri 07 Feb 2014 02:23:24 AM EST      0 KiB ./056_h2_f7_400/h2_f7_400_out.mph.status
Fri 07 Feb 2014 02:23:24 AM EST     64 KiB ./056_h2_f7_400/1579678.out
Fri 07 Feb 2014 03:47:31 AM EST 8132224 KiB ./057_h2_f7_10/h2__rh_1e-5.mph
Fri 07 Feb 2014 04:00:49 AM EST 8132224 KiB ./057_h2_f7_10/h2_f7_10_out_Model.mph
Fri 07 Feb 2014 04:00:49 AM EST      0 KiB ./057_h2_f7_10/h2_f7_10_out.mph.status
Fri 07 Feb 2014 04:00:49 AM EST     64 KiB ./057_h2_f7_10/1579679.out
Fri 07 Feb 2014 09:47:18 AM EST   9280 KiB ./056_h2_f7_400/h2__rh_4e-4.mat
Fri 07 Feb 2014 10:51:23 AM EST   9728 KiB ./018_bidomain/h2_plain__rh_1e-5.mat
Fri 07 Feb 2014 10:58:33 AM EST   9568 KiB ./057_h2_f7_10/h2__rh_1e-5.mat
Fri 07 Feb 2014 05:05:38 PM EST     64 KiB ./058_h2_f7_stationary/h2_f7_stationary.java
Fri 07 Feb 2014 06:06:29 PM EST     32 KiB ./058_h2_f7_stationary/slurm.slurm
Sat 08 Feb 2014 03:42:07 AM EST      0 KiB ./058_h2_f7_stationary/1581061.err
Sat 08 Feb 2014 03:42:14 AM EST     64 KiB ./058_h2_f7_stationary/h2_f7_stationary.class
Sat 08 Feb 2014 03:58:28 AM EST  70016 KiB ./058_h2_f7_stationary/h2s__rh_1e-5.mph
Sat 08 Feb 2014 04:12:40 AM EST  70304 KiB ./058_h2_f7_stationary/h2s__rh_4e-4.mph
Sat 08 Feb 2014 04:12:53 AM EST  70304 KiB ./058_h2_f7_stationary/h2_f7_stationary_out_Model.mph
Sat 08 Feb 2014 04:12:53 AM EST      0 KiB ./058_h2_f7_stationary/h2_f7_stationary_out.mph.status
Sat 08 Feb 2014 04:12:53 AM EST     32 KiB ./058_h2_f7_stationary/1581061.out
Mon 10 Feb 2014 11:40:54 AM EST    224 KiB ./058_h2_f7_stationary/h2s__rh_4e-4.mat
Mon 10 Feb 2014 11:42:32 AM EST    224 KiB ./058_h2_f7_stationary/h2s__rh_1e-5.mat
Mon 10 Feb 2014 11:50:08 AM EST     32 KiB ./plot_grid.m

J'ai délibérément choisi un champ de taille de fichier de 6 caractères, car s'il est plus long, il devient difficile de distinguer visuellement la taille des fichiers. De cette façon, les fichiers de plus de 1e6 KiB ressortent : par 1 caractère, on entend 1-9 Go, par 2 caractères, 10-99 Go, etc.


Edit : voici une autre version (depuis find . -printf "%Tc" sur MinGW/MSYS) :

find . -type f -printf "%T@\t%p\n" | sort -n | cut -f 2- | xargs -I{} ls -Glath --si {}

En donnant des résultats comme :

-rw-r--r-- 1 es 23K Jul 10  2010 ./laptop_0000071.jpg
-rw-r--r-- 1 es 43M Jul 29 19:19 ./work.xcf
-rw-r--r-- 1 es 87K Jul 29 20:11 ./patent_lamps/US Patent 274427 Maxim Lamp Holder.jpg
-rw-r--r-- 1 es 151K Jul 29 20:12 ./patent_lamps/Edison screw-in socket.png
-rw-r--r-- 1 es 50K Jul 29 20:13 ./patent_lamps/1157 Lamp.jpg
-rw-r--r-- 1 es 38K Jul 29 20:14 ./patent_lamps/US06919684-20050719-D00001.png

Où :

  • -I{} provoque l'apparition de {} pour être remplacé par un argument, y les nouvelles lignes sont maintenant les séparateurs d'arguments (notez les espaces dans les noms de fichiers ci-dessus).

  • ls -G supprime l'impression du nom du groupe (gaspillage d'espace).

  • ls -h --si produit des tailles de fichiers lisibles par l'homme (plus correct avec --si ).

  • ls -t trie par temps, ce qui n'est pas pertinent ici, mais c'est ce que j'utilise généralement.

1 votes

Note : pour trier par fichier taille à la place, il suffit de remplacer le T@ par s dans l'une ou l'autre des commandes ci-dessus.

0 votes

Celui-ci semble être le plus rapide

13voto

user399969 Points 11

J'ai une solution simple qui fonctionne à la fois pour FreeBSD (OS X) et Linux :

find . -type f -exec ls -t {} +

1 votes

Cela fonctionne parfaitement - devrait être la bonne réponse, ou au moins la mieux notée !

0 votes

find . -type f -exec ls -lat {} + vous donne une meilleure image avec la date et l'heure, si quelqu'un a besoin de ce format

0 votes

Ceci devrait être la meilleure réponse. Simple, facile à comprendre. La clé est le signe plus à la fin. Cela permet au find d'appeler ls une seule fois.

SistemesEz.com

SystemesEZ est une communauté de sysadmins où vous pouvez résoudre vos problèmes et vos doutes. Vous pouvez consulter les questions des autres sysadmins, poser vos propres questions ou résoudre celles des autres.

Powered by:

X