web-dev-qa-db-fra.com

Liste des fichiers triés numériquement

J'ai un tas de fichiers de log1 à log164.

J'essaie de LISTER le répertoire (trié) dans un terminal UNIX mais les fonctions de tri ne fournissent que le format comme ceci:

home:logs Home$ ls -1 | sort
log1.gz
log10.gz
log100.gz
log101.gz
log102.gz
log103.gz
log104.gz
log105.gz
log106.gz
...etc

Ce que je veux c'est

home:logs Home$ ls -1 | sort
log1.gz
log2.gz
log3.gz
log4.gz
log5.gz
log6.gz
log7.gz
...{more here}
log99.gz
log100.gz
log101.gz
log102.gz
...etc

Des suggestions sur ce que je pourrais utiliser pour ce faire?

134
Rabiani

bash accolades, {}, les énumérera dans l'ordre:

for file in log{1..164}.gz; do
    process "$file"
done
40
Kevin

Pourquoi ne pas utiliser la fonction intégrée ls pour ce cas particulier:

-v natural sort of (version) numbers within text

Par exemple ls -1v log*

293
lik

Avec GNU ls (c'est-à-dire sous Linux, Cygwin ou d'autres systèmes sur lesquels GNU ls est spécifiquement installé)):

ls -v

En zsh:

echo *(n)

Dans d'autres coquilles:

echo log?.gz log??.gz log???.gz

Remplacez echo par printf '%s\n' si vous voulez que chaque nom de fichier soit sur une ligne distincte.

Si vous souhaitez également des métadonnées de fichier (ls -l) et vous n'avez pas GNU ls, vous devrez appeler ls séparément pour chaque nom de fichier ou groupe de noms de fichier que vous souhaitez voir en lexicographique ordre.

ls -ld log?.gz; ls -ld log??.gz; ls -ld log???.gz

Pour éviter ces difficultés, utilisez suffisamment de zéros non significatifs dans les noms de vos fichiers pour que le tri lexicographique soit convivial (log001.gz, etc).

Alors que la solution ls -1v est certainement le plus agréable dans ce cas particulier, je pense qu'il est bon d'en avoir un qui fonctionne avec sort comme dans la question d'origine, car cela fonctionne également lorsque votre entrée ne provient pas de ls. Dans ce cas, vous pouvez utiliser:

ls -1 | sort -n -k1.4

Le -n l'option indique à sort de trier numériquement et -k 1.4 définit la clé de tri sur le premier champ (qui est le nom de fichier complet dans ce cas) à partir du 4ème caractère jusqu'au dernier.

29
Elmar Zander

Le GNU sort (comme disponible sur Linux,) a un mode de "tri de version" qui interprète les nombres à l'intérieur des non-nombres exactement comme vous le demandez:

De man 1 sort:

    -V, --version-sort
           natural sort of (version) numbers within text

(Création de fichiers de test vides à répertorier:
touch log1.gz log2.gz log3.gz log99.gz log100.gz log101.gz log102.gz)

Votre exemple de cas, en ajoutant le -V option (ou --version-sort):

ls -1 log*.gz | sort -V
log1.gz
log2.gz
log3.gz
log99.gz
log100.gz
log101.gz
log102.gz
24
Volker Siegel

si vous utilisez Mac ou BSD, essayez ceci:

ls -1 *.jpg | sort -n
8
Salvador Almaraz

Ma version de Solaris ne prend pas en charge ls -v (grrr). Et la solution de tri fournie ci-dessus 1) nécessite la connaissance de la position des chiffres dans le nom de fichier et 2) ne gère pas des choses comme les numéros de version en plusieurs parties.

L'approche ci-dessous est compatible avec Solaris, ne nécessite pas de connaissance préalable des positions des chiffres et gère les numéros de version avec 2, 3 ou 4 composants (comme: a-1.2, foo-5.6.7, bar_baz_9.10.11.12). Il utilise également sort -f pour replier les majuscules et les minuscules ensemble et gère correctement les répertoires entremêlés de fichiers:

ls -d | sort -f -t . -k 1,1 -k 2,2n -k 3,3n -k 4,4n

Notez que cette version limite le premier composant à un seul chiffre.

Si votre système d'exploitation cible prend en charge ls -v, c'est clairement la solution supérieure.

3
MykennaC

Solution Perl:

ls log*.gz | Perl -ne 'sub getnum{ $_[0] =~ /log(\d+)\.gz/; $1 }; Push @A, $_; END{ print sort { getnum $a <=> $b } @A}'
1
$ ls
log101.gz  log102.gz  log103.gz  log104.gz  log105.gz  log106.gz  log10.gz  log1.gz
$ ls | sort -t . -n -k1.4
log1.gz
log10.gz
log101.gz
log102.gz
log103.gz
log104.gz
log105.gz
log106.gz
1
kjohri

Cela a fonctionné pour moi.

J'ai des fichiers 1.jpg 2.jpg ... 18.jpg

$ echo *.jpg | tr -s ' ' '\n' | sort -n

sort se confond avec la sortie de ls en raison de caractères de couleur non imprimables. Si vous essayez ceci:

ls -1 --color=none *.jpg | sort -n

cela fonctionnera parfaitement.

sort peut ignorer les caractères non imprimables avec l'option -i mais cela ne fonctionne toujours pas et je ne sais pas pourquoi.

Mais vous pouvez toujours dépouiller la couleur comme ceci et sort fonctionnera:

ls -1 --color=always *.jpg | sed -r "s/\x1B\[([0-9]{1,2}(;[0-9]{1,2})?)?[mGK]//g" | sort -n

J'espère qu'un jour sort aura une option pour cela.

0
cy8g3n