Listando arquivos em um diretório, incluindo o conteúdo de subpastas com classificação

9

Estou procurando listar todo o conteúdo de um diretório, incluindo o conteúdo de subpastas, mas classificado por tamanho de arquivo. Até agora, eu consegui chegar até a listagem e a classificação enquanto ainda estava sendo recursivo ls -lhSR( hé bom ter isso, mas definitivamente não é essencial para mim, desde que eu possa obter tamanhos de arquivo). Provavelmente estou ignorando algo óbvio ou pedindo o impossível, mas qualquer conselho aqui seria muito apreciado.

toms
fonte

Respostas:

15

Você pode usar o find:

find . -type f -printf "%s %P\n" | sort -n

Opcional: Para converter valores de bytes em formato legível por humanos, adicione este:

| numfmt --to=iec-i --field=1

Explicação:

 find in current directory (.) all files (-type f) 

 -printf: suppress normal output and print the following:
     %s - size in bytes
     %P - path to file
     \n - new line

 | sort -n: sort the result (-n = numeric)
pLumo
fonte
Oh perfeito! Muito obrigado, isso fez exatamente o que eu precisava!
toms
3
Estou feliz que minha resposta tenha ajudado. Por favor, considere clicar na marca de seleção no lado esquerdo para marcar a resposta aceita. Obrigado.
PLumo
11
@RoVo também seria bom rever a pergunta, pois, como você a respondeu, provavelmente a achou interessante e útil.
terdon
Isso é verdade e eu fiz isso agora ;-)
pLumo
@toms Não há problema em esperar um pouco (talvez um dia ou mais) para aceitar a resposta, mesmo que seja tão boa quanto esta. Uma vez que a resposta é aceita, não há como outra resposta ser ainda melhor. E por causa disso, muitas pessoas não se incomodam em enviar outras respostas, por isso não temos a chance de vê-las para descobrir se são melhores.
Monty mais dura
7

Como você não especificou um shell específico, eis uma alternativa usando os qualificadores glob do zsh com

setopt extendedglob

para a recursão. Então, por exemplo:

  1. liste recursivamente os arquivos simples:

    printf '%s\n' **/*(.)
  2. listar recursivamente arquivos deslizantes, o rdered por em vincando L ength (ou seja, tamanho):

    printf '%s\n' **/*(.oL)
  3. recursivamente lista arquivos deslizantes, O rdered por de tamanho vincar:

    printf '%s\n' **/*(.OL)
  4. liste recursivamente os arquivos simples, ordenados por tamanho decrescente, e selecione os 3 principais resultados:

    printf '%s\n' **/*(.OL[1,3])

Se você quiser os tamanhos de arquivo também, poderá usar

du -hb **/*(.OL[1,3])
chave de aço
fonte
4

Com a globstaropção de shell definida, você pode usar o globbing do shell:

shopt -s globstar         # don’t match hidden files
shopt -s globstar dotglob # match hidden files
stat -c"%s %n" **/* | sort -n

Se você tentar isso com muitos arquivos, receberá um erro "Lista de argumentos muito longa". Para contornar isso, você pode usar printfe xargs:

printf "%s\0" **/* | xargs -0 stat -c"%s %n" | sort -n

Acabei de perceber que isso imprime os diretórios (com um tamanho de 4096 bytes) também - se você não quiser, use isso:

stat -c"%A %s %n" **/* | sed '/^d/d;s/\S* //' | sort -n
printf "%s\0" **/* | xargs -0 stat -c"%A %s %n" | sed '/^d/d;s/\S* //' | sort -n

Exemplo de execução

$ tree
.
├── edits.png
├── makescript
├── new
   └── edits.png
└── test
    └── 1.png

2 directories, 4 files
$ stat -c"%s %n" **/* | sort -n
0 test/1.png
43 makescript
2160 edits.png
2160 new/edits.png
4096 new
4096 test
$ stat -c"%A %s %n" **/* | sed '/^d/d;s/\S* //' | sort -n
0 test/1.png
43 makescript
2160 edits.png
2160 new/edits.png
sobremesa
fonte
Ótima solução. Comparado a encontrar, ele não inclui arquivos ocultos, como conseguir isso?
PLumo
@RoVo Sempre esqueça isso - você só precisa definir a dotglobopção de shell, veja minha resposta atualizada.
Sobremesa
Em vez de descascar diretórios após o fato com sed, você poderia considerar algo comoprintf "%s\0" **/* | xargs -0 sh -c 'for f; do [ -d "$f" ] || stat -c "%s %n" "$f"; done' sh | sort -n
steeldriver
Você pode usar ls -lhSd **/*se não se importar de ter os diretórios como parte da lista. Ou se nenhum dos seus nomes de diretório têm .neles, e todos os arquivos que você quer fazer , você pode ll -hS **/*.*, ou similar.
Peter Cordes
transformou isso em uma resposta
Peter Cordes
3

Se você não possui zsh, ainda pode usar du+ sort:

  1. Tamanhos legíveis por humanos, incluindo tamanhos cumulativos de diretórios:

    du --apparent-size -ah0 . | sort -zh | xargs -0L1
    
  2. Somente arquivos (usando find):

    find . -type f -print0 |
      du --files0-from=- --apparent-size -ah0 |
      sort -zh |
      xargs -0L1
    

Em ambos os casos, eu optaram por utilizar linhas de terminação nula ( -0, -z, -print0opções), para ser seguro contra todos os nomes de arquivos válidos.

muru
fonte
0

Para um uso interativo rápido em árvores de diretório que não são muito grandes, shopt -s globstaré muito bom. Um glob não pode filtrar os diretórios com base no tipo, mas se você usá-lo ls -d, lsapenas imprimirá o nome do diretório, em vez do conteúdo.

Supondo que seu llalias inclua -lh:

  # with  shopt -s globstar   in your .bashrc
ll -rSd **/*

fornecerá uma saída assim (do meu diretório code-golf), mas com realce de cores (para que seja mais fácil ver os diretórios). Observe que a classificação por tamanho do arquivo ocorreu entre subdiretórios.

drwxr-xr-x 1 peter peter   70 Jun  8 07:56 casexchg
...
drwxr-xr-x 1 peter peter  342 Mar 13 18:47 parity-party
-rw-r--r-- 1 peter peter  387 Jul 29  2017 likely.cpp
-rw-r--r-- 1 peter peter  416 Aug 31  2017 true-binary.asm~
-rw-r--r-- 1 peter peter  447 Feb 23 20:14 weight-of-zero.asm
...
-rw-r--r-- 1 peter peter 6.4K Jun  1  2017 string-exponential.asm
-rwxr-xr-x 1 peter peter 6.7K Aug 31  2017 true-binary
-rwxr-xr-x 1 peter peter 6.8K Sep 17  2017 dizzy-integer
-rw-r--r-- 1 peter peter 7.5K Jul 24  2017 fibonacci/fibonacci-1G.v3-working-32b-stack-except-output.asm
-rw-r--r-- 1 peter peter 8.4K Jul 25  2017 fibonacci/perf.32bit-pop-114limb.sub-cmc.1G~
-rw-r--r-- 1 peter peter 8.4K Jul 25  2017 fibonacci/perf.32bit-pop-114limb.sub-cmc.1G
-rwxr-xr-x 1 peter peter 8.4K May 19 04:29 a.out
-rw-r--r-- 1 peter peter 8.9K Jul 25  2017 fibonacci/perf.python-xnor-2n
-rw-r--r-- 1 peter peter 9.5K Jul 26  2017 fibonacci/fibonacci-1G-performance.asm
-rwxr-xr-x 1 peter peter 9.6K Apr 12 23:25 empty-args
-rw-r--r-- 1 peter peter 9.7K Dec 18 17:00 bubblesort.asm
-rwxr-xr-x 1 peter peter 9.9K Feb  6 23:34 parity-party/a.out
-rw-r--r-- 1 peter peter 9.9K Jul 25  2017 fibonacci/fibonacci-1G-performance.asm~
...

Você pode filtrar os diretórios através de grep -v '^d'

Às vezes, você pode usar um globo que corresponda apenas a arquivos e não a diretórios, se os nomes de arquivos tiverem um padrão. por exemplo ll -rSd **/*.jpg, ou até **/*.*funciona se nenhum dos nomes de diretório tiver .neles e todos os arquivos que você deseja fazer .

(Para pessoas com experiência em DOS: não há nada mágico *.*no Unix. Apenas corresponde a qualquer entrada de diretório que contenha um ponto literal. Mas, além de executáveis ​​e, às vezes, arquivos de texto, é comum dar extensões aos nomes de arquivos.)

O @dessert aponta que você precisaria shopt -s dotglobpara corresponder a todos os arquivos.


Com GNU find

Se não houver muitos arquivos para caber em uma lslinha de comando, find -exec ls {} +todos eles serão colocados na linha de comando, onde lspodem ser classificados.

find -not -type d -exec ls --color -lrSh {} +

Usar em -not -type dvez de -type fevitar ignorar links simbólicos, pipes nomeados, soquetes, arquivos de dispositivos e tudo o mais que você tiver em seus diretórios.


Com du:

du -ach | sort -h
....
4.0K    x86-modedetect-polyglot.o
8.0K    ascii-compress-base.asm
8.0K    dizzy-integer
8.0K    stopwatch-rdtsc.asm
8.0K    string-exponential.asm
8.0K    true-binary
12K     a.out
12K     bubblesort.asm
12K     casexchg
12K     empty-args
100K    parity-party
220K    fibonacci
628K    total

Agora, os nomes dos diretórios são classificados na lista para somar o total de todo o seu conteúdo, mas os arquivos individuais ainda estão incluídos.

sort -h, também conhecido como --human-numeric-sort, classifica números com sufixos de tamanho, como du -himpressões. É perfeito para uso com du.

Costumo usar du -sch * | sort -hou */obter apenas diretórios.

du -sch **/* | sort -hdaria a você a saída acima, se você esquecer que dutem uma -aopção.

(Levei apenas um tempo para procurá-lo porque estou postando uma resposta. Para uso interativo, provavelmente eu teria usado du -sch **/*.

Peter Cordes
fonte