Listar diretórios com base no tamanho do maior para o menor na linha única

5

Eu posso usar o seguinte comando para obter uma lista de diretórios e seus tamanhos e classificá-los do maior para o menor (no exemplo, renomeiei os diretórios para números para facilitar a compreensão).

$: du -sk [a-z]* 2>/dev/null | sort -nr
413096  one
106572  two
97452   three
76428   four
55052   five
45068   six
33680   seven
23220   eight
17716   nine

Estou escrevendo um programa que requer a entrada desses diretórios do maior para o menor, mas, para questões de conveniência, eles precisam de todos eles em uma linha. Existe um comando que me permita classificar os diretórios do maior para o menor em uma linha sem o tamanho?

Eu gostaria que a saída fosse assim:

one two three four five six seven eight nine
    
por etho201 23.05.2014 / 23:38

5 respostas

3

Se você tiver certeza de que os nomes dos diretórios não contêm espaço em branco, é simples obter todos os nomes de diretório em uma linha:

du -sk [a-z]*/ 2>/dev/null | sort -nr | awk '{printf $2" "}'

Obtendo as informações no python

Se você deseja capturar essa saída em um programa python e transformá-la em uma lista. Usando python2.7 ou melhor:

import subprocess
dir_list = subprocess.check_output("du -sk [a-z]*/ 2>/dev/null | sort -nr | awk '{printf $2\" \"}'", shell=True).split()

Em python2.6:

import subprocess
subprocess.Popen("du -sk [a-z]*/ 2>/dev/null | sort -nr | awk '{printf $2\" \"}'", shell=True, stdout=subprocess.PIPE).communicate()[0].split()

Também podemos aproveitar os recursos do Python para reduzir a quantidade de trabalho feito pelo shell e, em particular, para eliminar a necessidade de awk :

subprocess.Popen("du -sk [a-z]*/ | sort -nr", shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate()[0].split()[1::2]

Pode-se ir mais além e ler a saída du diretamente no python, converter os tamanhos em números inteiros e classificar em tamanho. É mais simples, porém, fazer isso com sort -nr no shell.

Especificando um diretório

Se os diretórios cujo tamanho você deseja não estiverem no diretório atual, existem duas possibilidades:

du -sk /some/path/[a-z]*/ 2>/dev/null | sort -nr | awk '{printf $2" "}'

e também:

cd /some/path/ && du -sk [a-z]*/ 2>/dev/null | sort -nr | awk '{printf $2" "}'

A diferença entre esses dois é se /some/path está incluído na saída ou não.

    
por 23.05.2014 / 23:52
3

Usando paste

du -sk [a-z]* 2>/dev/null | sort -nr| cut -f2- | paste -s -
    
por 24.05.2014 / 00:19
2

zsh tem a capacidade de classificar seus globs usando qualificadores de globbing. Você também pode definir seus próprios qualificadores glob com funções. Por exemplo:

zdu() REPLY=$(du -s -- "$REPLY")

print -r -- [[:alpha:]]*(/nO+zdu)

imprime os diretórios ( / ) cujo nome começa com uma letra (btw, [a-z] só faz sentido no idioma C) numericamente (n) inverta ordenado (O) usando a função zdu .

Observe que quando você faz:

du -s a b

Se a e b contiverem hardlinks para os mesmos arquivos, o uso do disco será contado para a , mas não para b . A abordagem zsh aqui evita isso.

Se você for usar python, eu faria o mesmo a partir daí: chame du -s para cada um dos arquivos e classifique essa lista lá. Lembre-se de que os nomes dos arquivos podem conter qualquer caractere, incluindo espaço, tabulação e nova linha.

    
por 24.05.2014 / 01:14
0

Ou talvez algo assim

du -sk [a-z]* 2>/dev/null | sort -nr | awk '{print $2}' | sed ':a;N;$!ba;s/\n/ /g'

Isso lhe dará tudo em uma linha.

    
por 23.05.2014 / 23:58
0

Eu acredito que o comando du usa \t para separar o tamanho e o caminho do diretório, então você só precisa passar alguns parâmetros extras para awk :

du -sk [a-z]* 2>/dev/null | sort -nr | awk -F'\t' -v ORS=" " '{print $2}'

No caso improvável de os caminhos de diretório também conterem o caractere de tabulação, você pode remover o prefixo de tamanho primeiro:

du -sk [a-z]* 2>/dev/null | sort -nr | awk -v ORS=" " '{sub(/^[0-9]*\t/,"");print}'
    
por 24.05.2014 / 03:34