web-dev-qa-db-pt.com

Como ordenar os primeiros diretórios e depois os arquivos etc ... quando usar "ls" no Unix

Eu gostaria de usar o comando ls para mostrar primeiro diretórios e arquivos. Eu tentei:

ls -la | sort -k 1

Mas eu recebi um pedido errado.

86
atricapilla

O comando a seguir listará os diretórios primeiro, os arquivos comuns em segundo lugar e os links em terceiro.

ls -la | grep "^d" && ls -la | grep "^-" && ls -la | grep "^l"

Além disso, faria muito sentido criar um alias para esse comando salvar os pressionamentos de tecla.

Edit:

Se você quiser diretórios primeiro e depois tudo o que não for um diretório em segundo lugar, use isto:

ls -la | grep "^d" && ls -la | grep -v "^d"

26
eleven81

Eu amo tanto * nix e adoro ver a inventividade que entra em algumas dessas respostas ...

O meu não é tão chique em GNU Linux:

alias ls='ls --color -h --group-directories-first'

Dado que estou mais confortável com meus aplicativos Linux CLI, eu também tento atualizar o coreutils no OSX:

brew install coreutils
alias ls='/usr/local/bin/gls --color -h --group-directories-first'
197
jonathanserafini

Para usuários de Mac coreutils :

brew install coreutils

alias ls='ls --color -h --group-directories-first'

Assumindo que seu sistema está pronto para homebrew :

16
Vadym Tyemirov

Você tem várias opções, dependendo se quiser manter a ordem alfabética.

Você poderia simplesmente tentar:

ls -al | classificar -k1 -r

ou isto, para manter a ordem alfabética dos arquivos com as mesmas permissões:

ls -al | classificar -k1,1 -k9,9 -r

ou, como onze81 disse (mas esta versão lista tudo):

ls -la | grep "^ d" && ls -la | grep "^ -" && ls -al | grep -v "^ [d | -]"

6
Studer

Para delerious01 resposta, gostaria de acrescentar que, se você quiser ordenação de estilo antigo:

LANG=C ls -la --group-directories-first

(ou use LC_ALL ou LANGUAGE ou LC_COLLATE definido como "C").

Isso vai dar algo parecido com:

.
..
DIR
Dir
dir
.hidden
123
UC_FILE
Uc_file
lc_file

Embora, se bem me lembro, os arquivos de pontos ocultos apareceram originalmente antes dos diretórios.

5
Dennis Williamson

Há certas coisas que quero ver em uma listagem de diretório e, até o momento, nenhuma das respostas aqui atende a todos os requisitos abaixo. Meus requisitos para uma listagem de diretórios:

  1. Diretórios e arquivos são classificados em ordem alfabética
  2. Os diretórios são listados primeiro
  3. Links simbólicos (links simbólicos) são classificados como arquivos
  4. A classificação não faz distinção entre maiúsculas e minúsculas
  5. A classificação ignora todos os principais caracteres não alfa em um nome de arquivo
  6. A listagem inclui a contagem total de diretórios (excluindo ./ e ../), arquivos e links
  7. A listagem inclui o tamanho total (uso do disco) de diretórios e arquivos
  8. A listagem tem que ter a mesma aparência no Linux e no Windows (Git Bash Shell) - isso foi o mais difícil de acertar, já que opções convenientes como --group-directories-first não funcionam no Git Bash para Windows.

Depois de muita conversa, eu finalmente encontrei um one-liner (embora uma linha muito longa ;-)) com o qual estou satisfeito. Eu atribuí isso a um apelido chamado 'dir':

ls -dlF --color * .* | head -n2 && ls -AlF | LC_ALL=C grep "^d" | 
LC_ALL=C sort -k 9df && ls -AlF | LC_ALL=C grep "^[l-]" | 
LC_ALL=C sort -k 9df && echo -e `find -maxdepth 1 -type d ! -name . | 
wc -l` Dir\(s\) `du -hs | cut -f 1`\\t\\t`find -maxdepth 1 -type f | 
wc -l` File\(s\) `find -maxdepth 1 -type f -print0 | du -ch --files0-from=- | 
tail -n 1 | cut -f 1`\\t\\t`find -maxdepth 1 -type l | wc -l` Link\(s\)

Para tornar as coisas mais fáceis de gerenciar, criei comandos separados para enviar cada segmento da listagem de diretórios para o meu gosto e, em seguida, reuni-los usando o operador &&.

  • ls -dlF --color * .* | head -n2 - Extraia ./ e ../. Nós não queremos passar estes através de sort porque eles já estão na ordem correta, e classificá-los pode resultar em ../ sendo listado primeiro. A opção -d é para se livrar da linha "total"; Eu gosto de adicionar -F para mostrar a barra final para diretórios (ele também marcará links simbólicos com "@" quando você faz um ls -F simples).

  • ls -AlF | LC_ALL=C grep "^d" | LC_ALL=C sort -k 9df - Extraia os diretórios e classifique-os por nome de arquivo (9ª coluna), ignorando caracteres não-alfa/espaço (opção d) e caractere de caso (opção f). A opção ls -A exclui ./ e ../ da listagem, pois já as extraímos na etapa anterior. Prefiro todos os comandos grep e sort com a redefinição de localidade LC_ALL=C para que (1) a saída seja consistente entre shells Unix e (2) você possa ver um desempenho mais rápido, já que não tem mais a sobrecarga do UTF-8 pesado conjunto de caracteres para lidar.

  • ls -AlF | LC_ALL=C grep "^[l-]" | LC_ALL=C sort -k 9df - Isso é semelhante ao passo acima, mas desta vez estamos classificando arquivos e links simbólicos.

  • find -maxdepth 1 -type d ! -name . | wc -l - Obtém o número de diretórios, excluindo ./ e ../.

  • find -maxdepth 1 -type f | wc -l - Obtém o número de arquivos.

  • find -maxdepth 1 -type l | wc -l - Obtém o número de links simbólicos.

  • du -hs | cut -f 1 - Extrai o tamanho total de todos os subdiretórios em formato legível por humanos.

  • find -maxdepth 1 -type f -print0 | du -ch --files0-from=- | tail -n 1 | cut -f 1 - Extrai o tamanho total de todos os arquivos em formato legível.

Vamos ver nosso novo alias dir em ação!

ANTES:

$ ls -alF
total 22
drwxr-xr-x   13 Tom      Administ     4096 Oct 25 02:38 ./
drwxr-xr-x    3 Tom      Administ        0 Dec 24  2014 ../
drwxr-xr-x   15 Tom      Administ     4096 Sep 17 01:23 .VirtualBox/
-rw-r--r--    1 Tom      Administ      615 Oct 25 02:38 .aliases
-rw-r--r--    1 Tom      Administ    12742 Oct 24 11:47 .bash_history
-rw-r--r--    1 Tom      Administ     3234 Oct 24 15:06 .bash_profile
drwxr-xr-x    1 Tom      Administ        0 Jan 24  2015 .gem/
-rw-r--r--    1 Tom      Administ      586 Oct 24 03:53 .gitconfig
drwxr-xr-x    1 Tom      Administ     4096 Dec 28  2014 .ssh/
drwxr-xr-x    4 Tom      Administ        0 Jan 24  2015 .travis/
-rw-r--r--    1 Tom      Administ     6645 Oct 25 02:38 _viminfo
-rw-r--r--    1 Tom      Administ     4907 Oct 24 15:16 profile
drwxr-xr-x    1 Tom      Administ        0 Oct 24 22:20 tmp/

DEPOIS DE:

$ dir
drwxr-xr-x   13 Tom      Administ     4096 Oct 25 02:38 ./
drwxr-xr-x    3 Tom      Administ        0 Dec 24  2014 ../
drwxr-xr-x    1 Tom      Administ        0 Jan 24  2015 .gem/
drwxr-xr-x    1 Tom      Administ     4096 Dec 28  2014 .ssh/
drwxr-xr-x    1 Tom      Administ        0 Oct 24 22:20 tmp/
drwxr-xr-x    4 Tom      Administ        0 Jan 24  2015 .travis/
drwxr-xr-x   15 Tom      Administ     4096 Sep 17 01:23 .VirtualBox/
-rw-r--r--    1 Tom      Administ      615 Oct 25 02:38 .aliases
-rw-r--r--    1 Tom      Administ    12742 Oct 24 11:47 .bash_history
-rw-r--r--    1 Tom      Administ     3234 Oct 24 15:06 .bash_profile
-rw-r--r--    1 Tom      Administ      586 Oct 24 03:53 .gitconfig
-rw-r--r--    1 Tom      Administ     4907 Oct 24 15:16 profile
-rw-r--r--    1 Tom      Administ     6645 Oct 25 02:38 _viminfo
      5 Dir(s) 2.8M           6 File(s) 31K           0 Link(s)

Uma pequena desvantagem é que você não pode ter listas coloridas, já que os caracteres de controle de cores que cercam os nomes dos arquivos tornam a classificação muito pouco confiável.


UPDATE

O alias acima era dolorosamente lento quando executado a partir do diretório raiz de um sistema de arquivos profundo, então atualizei para este comando mais simples, mas com muito mais desempenho:

ls -AFoqv --color --group-directories-first | tail -n +2 && find -maxdepth 1 -type f -printf '%s\n' | awk '{total+=$1} END {print total" bytes"}'

Amostra de saída:

$ dir
drwxr-xr-x 1 Tom     0 Mar 29 13:49 .aws/
drwxr-xr-x 1 Tom     0 Mar 29 13:49 .gem/
drwxr-xr-x 1 Tom     0 Mar 29 19:32 .ssh/
drwxr-xr-x 1 Tom     0 Mar 29 13:49 .zbstudio/
drwxr-xr-x 1 Tom     0 Jun 16  2016 temp/
drwxr-xr-x 1 Tom     0 Jul 13  2016 vimfiles/
-rw-r--r-- 2 Tom   365 Mar 30 10:37 .aliases
-rw-r--r-- 1 Tom 16028 Mar 30 12:12 .bash_history
-rw-r--r-- 2 Tom  2807 Mar 30 12:12 .bash_profile
-rw-r--r-- 2 Tom  2177 Mar 29 23:24 .functions
-rw-r--r-- 1 Tom  1091 Mar 30 10:34 .gitconfig
-rw-r--r-- 1 Tom  8907 Mar 29 14:45 _viminfo
-rw-r--r-- 1 Tom  2444 Jul 13  2016 _vimrc
33819 bytes

Como a nova versão do Git Bash para Windows suporta --group-directories-first, não precisamos mais recorrer a sort. Mesmo que o novo alias não exiba tanta informação quanto o alias anterior, os ganhos de desempenho valem a pena. Como um bônus, você também ganha cores!

5
thdoan

ls -laX mostrará os diretórios primeiro em ordem alfabética, mas irá atarraxar a lista de arquivos.

Opções longas:

ls
    -l    # List
    --all
    -X    # Sort alphabetically by entry extension
2
Bobby

Aqui está uma função para fazer isso (bash ou zsh): E ... eu não estou sugerindo que esta é a melhor maneira, mas é a que eu inventei e estou usando agora:

 function lss 
 {
 # Mostra a lista de diretórios com diretórios no topo. 
 
 comando ls --color = always $ @ | egrep '^ d | total' 
 comando ls --color = sempre $ @ | egrep -v '^ d | total'; 
} 
2
SuperMagic

TL; DR

alias ls='ls -lhF --color'

list_sorted() {
    ls $* | grep "^d";
    ls $* | grep "^-";
    ls $* | grep -v -E "^d|^-|^total"
}

alias ll=list_sorted

Explicação

Eu uso uma combinação das soluções fornecidas nas respostas e comentários aqui.

Padrão ls

Primeiro de tudo, eu sobrescrevo o comportamento padrão para ls:

  • -l: Sempre exibe a lista como uma lista vertical unidimensional
  • -h: exibir tamanhos de arquivo em uma forma legível por humanos (por exemplo, 4,0K em vez de 4096)
  • -F: Exibir indicadores como uma barra final para diretórios
alias ls='ls -lhF --color'

ll estendido

Em seguida, escrevo uma função que contém a lógica de classificação. Para cada ls eu passo qualquer argumento originalmente passado para ele. Isso me permite usar o alias de um diretório de trabalho diferente daquele que eu quero listar (por exemplo, ls -a ~).

Além disso, cada chamada para ls é canalizada para um comando grep. Aqui, a classificação acontece. ls -l | grep "^d", por exemplo, apenas lista diretórios. Se diretórios devem ser listados primeiro, isso precisa vir em primeiro lugar na função também. A próxima coisa é arquivos.

Por fim, mostro tudo o que não é um diretório nem um arquivo (nem a linha mostrando o tamanho total do conteúdo do diretório). Isto é feito através do grepping directoy, das entradas regulares de arquivos e da entrada total e, em seguida, invertendo o resultado através do argumento -v.

list_sorted() {
    # List directories
    ls $* | grep "^d";
    # List regular files
    ls $* | grep "^-";
    # List everything else (e.g. symbolic links)
    ls $* | grep -v -E "^d|^-|^total"
}

Finalmente, eu alias a função para um novo comando. Em particular, não quero sobrescrever ls no caso de minha função quebrar em alguns cenários. Então eu quero poder usar ls. Como alternativa, você sempre pode chamar o comando ls sem serrilhado chamando \ls.

alias ll=list_sorted

Notas

  • Eu uso ; em vez de && como um delimitador para os comandos. Caso contrário, não é possível listar o conteúdo de diretórios que não contenham diretórios (o primeiro comando ls é avaliado como false, não permitindo a execução do próximo comando, já que é acoplado a &&. ; evita isso.)
1
kleinfreund

Outra maneira ...

find . -d 1 -type d | ls -la | sort -r 

OR

ls -la | sort -r

OR

d=`find . -type d -d 1`;f=`find . -type f -d 1`; echo -e -DIRS- "\n$d\n" -FILES- "\n$f"
1
Eddie B

Esta é uma solução de script. Lista apenas os nomes, sem dados inode, alfabéticos, sem diferenciação de maiúsculas e minúsculas, formatados em colunas. Embora seja o principal da linha em vez da coluna principal, como a saída padrão de ls. As colunas ficam um pouco confusas se houver um nome de arquivo com mais de 26 caracteres.

rm -f /tmp/lsout
ls -1p | grep / | sort -f >> /tmp/lsout
ls -1p | grep -v / | sort -f >> /tmp/lsout

IFS=$'\n' read -d '' -r -a lines < /tmp/lsout

printf "%-24s  %-24s  %-24s\n" "${lines[@]}"

E outro, com alguma formatação extra.

rm -f /tmp/lsout
echo "  ---- Directories ---- " >> /tmp/lsout
ls -1p | grep / | sort -f >> /tmp/lsout
IFS=$'\n' read -d '' -r -a lines < /tmp/lsout
printf "%-24s  %-24s  %-24s\n" "${lines[@]}"

rm -f /tmp/lsout
echo "  ------- Files ------- " >> /tmp/lsout
ls -1p | grep -v / | sort -f >> /tmp/lsout
IFS=$'\n' read -d '' -r -a lines < /tmp/lsout
printf "%-24s  %-24s  %-24s\n" "${lines[@]}"

Saída para o último se parece com o seguinte, menos as cores:

  ---- Directories ----   archive/                  bookmarks/              
Desktop/                  Documents/                Downloads/              
fff/                      health/                   Library/                
Movies/                   Music/                    Pictures/               
Public/                   rrf/                      scifi/            
testdir/                  testdir2/                                         
  ------- Files -------   @todo                     comedy            
delme                     lll                       maxims                  
schedule                  vtokens style

Apenas lembre-se de não aliasar ou alterar o comportamento padrão de ls desde que este script o chama.

0
Igorio