Listar arquivos classificados pelo número de linhas que eles contêm

32

Como posso listar o número de linhas nos arquivos /group/book/four/word, classificado pelo número de linhas que eles contêm?

ls -l O comando lista-os, mas não os classifica

Ken R
fonte
1
Deseja os arquivos listados por número de linhas ou lista o número de linhas nos arquivos ou em ambos? ls -lnão fornece o número de linhas. ls -lSclassifica o arquivo por tamanho com algumas lsimplementações ( tamanho sendo o número de bytes no conteúdo).
Stéphane Chazelas

Respostas:

34

Você deve usar um comando como este:

find /group/book/four/word/ -type f -exec wc -l {} + | sort -rn
  • find: pesquise arquivos no caminho que você deseja. Se você não deseja que seja recursivo e sua findimplementação o suporte, você deve adicionar um -maxdepth 1pouco antes da -execopção.
  • exec: diz ao comando para executar wc -lem todos os arquivos.
  • sort -rn: classifique os resultados numericamente na ordem inversa. De maior para menor.

(que assume que os nomes dos arquivos não contêm caracteres de nova linha).

jherran
fonte
Observe que, quando passados ​​mais de um arquivo (ou com algumas implementações, mais de um arquivo que ele pode ler), wctambém imprimirá uma totallinha; portanto, você também terá uma ou mais linhas "totais", a menos que haja apenas um arquivo . Você pode canalizar grep /para removê-los.
Stéphane Chazelas 28/02
upvote por causa de sortcomando
Francisco
como posso filtrar para mostrar apenas o arquivo com X linhas no mínimo (excluir X = 0 linha por exemplo)?
Matrix
11

Não recursivo

Provavelmente a versão mais simples se você não precisar de recursividade:

wc -l /group/book/four/word/*|sort -n

wcconta as linhas (opção -l) em todos os *arquivos (exceto os ocultos) ( ) abaixo /group/book/four/word/e sortclassifica o resultado (através do canal |) numericamente (opção -n).

Recursivo

Alguém fez um comentário a esta resposta mencionando grep -rlcantes para suprimi-la. De fato, grepé uma ótima alternativa, especialmente se você precisar de recursividade:

grep -rc '^' /group/book/four/word/|tr ':' ' '|sort -n -k2

contará (opção -c) de forma recursiva (opção -r) linhas de correspondência ( grep) '^'(isto é, a partir de linhas) no diretório /group/book/four/word/. Então você deve substituir os dois pontos por um espaço, por exemplo, usando tr, para ajudar sort, que deseja classificar numericamente (opção -n) na segunda coluna (opção -k2).

Atualização: Veja o comentário de Stephane sobre possíveis limitações e como você pode realmente se livrar tr.

Skippy le Grand Gourou
fonte
3
grep -c .conta as linhas que contêm pelo menos um caractere válido. Use grep -c '^'para contar todas as linhas (também contará caracteres à direita após a última nova linha com algumas grepimplementações). Observe que nem todas as grepimplementações suportam -rae o comportamento varia entre as que o fazem. Você não precisa converter :s (dois pontos, e não ponto e vírgula) em espaços para sort. Apenas use -t:. Observe que isso pressupõe que os nomes dos arquivos não contenham :caracteres em branco ou nova linha.
Stéphane Chazelas
1
Obrigado por postar sua solução não recursiva; Eu não sabia que wcdava um total tão útil se você passasse por vários caminhos. O acoplamento dessa funcionalidade ao curinga e ao tubo sorté realmente limpo.
Qcom 25/09/15
7

Com zsh:

lines() REPLY=$(wc -l < $REPLY)
printf '%s\n' /group/book/four/word/*(.no+lines)

Definimos uma nova função de classificaçãolines que responde com o número de linhas no arquivo. E usamos o o+linesqualificador glob que, junto com n(para classificação numérica), define como os resultados da glob são ordenados. ( .também adicionado para verificar apenas arquivos regulares).

Isso não assume que tipo de caractere os nomes de arquivo podem conter, exceto os arquivos ocultos (aqueles iniciados por .) são omitidos. Adicione o Dqualificador glob se você também quiser.

Stéphane Chazelas
fonte
2
OP está marcado com bashapenas ...
l0b0 27/11
7
@ l0b0 que não significa que a próxima pessoa que precisa disso também esteja executando o bash.
terdon
4

Você não especifica se também deseja os arquivos em qualquer subdiretório de /group/book/four/word. A findsolução na resposta de jherran descerá em subdiretórios. Se isso não for desejado, use o shell:

for file in ./*; do [ -f "$file" ] && wc -l "$file"; done | sort -n

Se os nomes dos seus arquivos puderem conter novas linhas, você poderá usar algo como:

for file in ./*; do 
    [ -f "$file" ] && 
        printf "%lu %s\0" "$(wc -l < "$file")" "$file"
done | sort -zn | tr '\0' '\n'

Finalmente, se você faz querer descer para os subdiretórios, você pode usar isso em bash4 ou superior:

shopt -s globstar
for file in ./**/*; do [ -f "$file" ] && wc -l "$file"; done | sort -n

Observe que as versões bashanteriores à 4.3 seguiam links simbólicos ao descer recursivamente a árvore de diretórios (como zsh's ou tcsh' s ***/*).

Além disso, todas as soluções acima ignoram os arquivos ocultos (aqueles cujo nome começa com a ., costumam shopt -s dotglobincluí-los) e também incluem a contagem de linhas de links simbólicos (que a findabordagem não incluirá).

terdon
fonte
Observe que outras diferenças da solução da jherran é que a sua também considerará o link simbólico para arquivos regulares ( -xtype fno GNU find ou *(-.)no zsh) e omitirá os arquivos ocultos.
Stéphane Chazelas 27/11/14
@ StéphaneChazelas obrigado, esclarecido. Por que o %luin printf? Pelo que me lembro, isso significa decimal longo sem sinal, é realmente necessário? Por que não tratar o número como uma string? Isso faz diferença?
terdon
2
Se a saída wc estiver vazia (por exemplo, porque o arquivo não é legível), será expandida para em 0vez da string vazia, que é um pouco melhor. Algumas implementações de classificação funcionam com números inteiros não assinados, outros com assinados. %luparece a aposta mais segura, mas provavelmente não importa como se você tivesse 2^31linhas, isso levará anos de qualquer maneira.
Stéphane Chazelas
1

Se você deseja instalar fdum localizador de arquivos muito rápido, escrito em Rust (você deve instalá-lo, é ótimo ter mesmo assim)

fd --type=file . | xargs wc -l | sort -n

Basicamente, fdlista os arquivos, o xargs passa a lista de arquivos wc(significa contagem de palavras, mas passar -l fará com que conte linhas) e, finalmente, é classificado do menor número de linhas para o maior uso sort -n.

JustGage
fonte