Comment trier la taille lisible par l'homme

11

Je cherche essentiellement des fichiers, puis je trie par taille. Le script fonctionne si je ne trie pas la taille par lisible par l'homme. Mais je veux que la taille soit lisible par l'homme. Comment trier des tailles lisibles par l'homme?

Par exemple:

 ls -l | sort -k 5 -n | awk '{print $9 " " $5}'

Cela fonctionne comme prévu, j'ai la taille de mes fichiers en octets croissante:

1.txt 1
test.txt 3
bash.sh* 573
DocGeneration.txt 1131
andres_stuff.txt 1465
Branches.xlsx 15087
foo 23735
bar 60566
2016_stuff.pdf 996850

Maintenant, je veux que la taille soit lisible par l'homme, j'ai donc ajouté un paramètre -h à ls, et maintenant certains fichiers sont hors service:

 ls -lh | sort -k 5 -n | awk '{print $9 " " $5}'
1.txt 1
DocGeneration.txt 1.2K
andres_stuff.txt 1.5K
test.txt 3
Branches.xlsx 15K
foo 24K
bar 60K
bash.sh* 573
2016_stuff.pdf 974K

tvo000
la source
-k 5- Comment ça marche?
ctrl-alt-delor
@ ctrl-alt-delor: je crois que la taille est dans la 5ème colonne de la lssortie
jesse_b
2
Utiliser duau lieu de lspourrait être une bonne idée.
Xenoid
... ou find« s -printfavec son %pet %sformatteurs (suivie d'une « humanisation » des tailles).
Stephen Kitt
@Jesse_b mon erreur, j'ai juste supposé que les données dans la question (marquées comme c'est ce que j'avais) étaient les entrées triées.
ctrl-alt-delor

Réponses:

28

Essayer sort -h k2

-h, --human-numeric-sort compare les nombres lisibles par l'homme (par exemple, 2K 1G)

Cela fait partie du tri gnu, du tri BSD et autres.

ctrl-alt-delor
la source
5
Ne faut-il pas analyser la sortie de ls?
3
@Tomasz Pas toujours. S'il fournit la sortie dont vous avez besoin, le rediriger vers une autre opération de formatage n'est pas particulièrement dangereux. Ce que vous ne devez pas faire, c'est boucler sur la sortie de lset utiliser à la place la globalisation de fichiers directement. Globbing seul ne fonctionnera pas ici. Cela dit, je préférerais probablement ducela.
Bloodgain
1
@Bloodgain le format ls n'est pas garanti d'être le même à travers les binaires systèmes / ls, donc le analyser de manière portable est considéré comme impossible.
D. Ben Knoble
1
De plus, les noms de fichiers avec des espaces blancs vont perturber les choses
D. Ben Knoble
1
@Bloodgain: files=(); for f in *; do [[ -L "$f" ]] && files+=("$f"); done; echo ${#files[@]}(Je pourrais avoir un commutateur de test de lien symbolique incorrect). Si vous ne vous souciez pas des liens symboliques, files=(*); echo ${#files[@]}qui devient portable si vous utilisez setet non des tableaux.
D. Ben Knoble
29

lsa cette fonctionnalité intégrée, utilisez l' -Soption et triez dans l'ordre inverse:ls -lShr

       -r, --reverse
              reverse order while sorting

       -S     sort by file size, largest first
Mark McKinstry
la source
1
-hn'est pas une option standardls , mais doit être utilisable si OP l'a déjà. Le reste est standard, et c'est certainement la réponse que j'aurais écrite.
Toby Speight
5
+1 Ne vous embêtez pas à analyser la sortie de ls.
David Richerby
C'est la meilleure réponse, mais elle devrait inclure les informations dans le commentaire de @ Toby: -Speut-être pas disponible pour votre ls. FWIW, -Sest pris en charge même avec la bibliothèque d'Emacs ls-lisp.el, qui est utilisée lorsque le système d'exploitation n'a pas ls. Cela fonctionne par exemple dans Emacs sur MS Windows.
Drew
Cela devrait être la réponse acceptée.
scatter
1
@Drew: Le commentaire de Toby dit que ce -hn'est peut-être pas universellement disponible, mais OP l'utilise déjà de toute façon. devrait-S vraiment être universellement disponible, car c'est dans le lien POSIX que Toby fournit. Cependant, il existe de nombreuses boîtes à outils non POSIX.
Kevin
5

Puisqu'aucun shell spécifique n'a été mentionné, voici comment faire le tout dans le zshshell:

ls -lhf **/*(.Lk-1024oL)

Le **modèle de glob correspond à *mais /dans les chemins d'accès, c'est-à-dire comme le ferait une recherche récursive.

La lscommande activerait les tailles lisibles par l'homme avec -het le format de sortie de longue liste avec -l. L' -foption désactive le tri, il lssuffit donc de répertorier les fichiers dans l'ordre où ils sont donnés.

Cet ordre est organisé par le **/*(.Lk-1024oL)modèle de globbing de nom de fichier afin que les petits fichiers soient répertoriés en premier. Le **/*bit correspond à chaque fichier et répertoire de ce répertoire et ci-dessous, mais (...)modifie le comportement du glob (c'est un "qualificatif glob").

C'est oLà la fin que trie ( o) les noms par taille de fichier ( L, "longueur").

Au .début, le glob ne correspond qu'aux fichiers normaux (pas de répertoires).

Le Lk-1024bit sélectionne les fichiers dont la taille est inférieure à 1024 Ko ("longueur en Ko inférieure à 1024").

Si ce zshn'est pas votre shell interactif principal, vous pouvez utiliser

zsh -c 'ls -lf **/*(.Lk-1024oL)'

Utilisez setopt GLOB_DOTS(ou zsh -o GLOB_DOTS -c ...) pour faire correspondre également les noms masqués. ... ou ajoutez simplement Dà la chaîne de qualificatif glob.


En développant ce qui précède, en supposant que vous souhaitiez une sortie à 2 colonnes avec des noms de chemin et des tailles lisibles par l'homme, et en supposant également que vous disposez numfmtde GNU coreutils,

zmodload -F zsh/stat b:zstat

for pathname in **/*(.Lk-1024oL); do
    printf '%s\t%s\n' "$pathname" "$(zstat +size "$pathname" | numfmt --to=iec)"
done

ou, plus vite,

paste <( printf '%s\n' **/*(.Lk-1024oL) ) \
      <( zstat -N +size **/*(.Lk-1024oL) | numfmt --to=iec )
Kusalananda
la source
4

Si votre sortn'a pas l' -hoption, vous pouvez utiliser une commande awk (bien que très longue) comme la suivante:

find . -type f -size -1024k -exec ls -al {} \; | sort -k 5 -n | awk '{if ($5 > 1099511627776) {print $9,$5/1024/1024/1024/1024"T"} else if ($5 > 1073741824) {print $9,$5/1024/1024/1024"G"} else if ($5 > 1048576) {print $9,$5/1024/1024"M"} else if ($5 > 1024) {print $9,$5/1024"K"} else {print $9,$5"B"}}' | column -t

Cela triera votre sortie en octets, puis les convertira à leur taille lisible par la suite.

jesse_b
la source
-1

Est-ce que cela fonctionnerait?

ls -l | awk '{if ($5<=1024) {print}}' | sort -k 5 -n | awk '{print $9"\t"substr($5/1024,1,3)"k"} '| column -t

La première awkexp recherchera les fichiers inférieurs à 1 Mo et la seconde prendra la taille en octets du résultat et la convertira en Ko et imprime les 3 premiers éléments pour donner une taille lisible par l'homme.

Vignesh SP
la source
Cela ne résout pas vraiment la question des OP - il ne regarde que dans le répertoire courant et n'imprimera que les fichiers normaux. Comparera également contre 1 Ko au lieu de 1 Mo. Enfin, nous recherchons des réponses avec des explications sur le fonctionnement du code.
grochmal
Mon mauvais a ajouté ce qu'il fait.
Vignesh SP