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

78

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.

    
por atricapilla 16.02.2010 / 14:13

11 respostas

25

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

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

Além disso, seria sensato criar um alias para que esse comando salvasse toques de tecla.

Editar:

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

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

    
por 16.02.2010 / 14:36
181

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

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

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

Dado que estou mais confortável com meus aplicativos Linux CLI, também tenho a tendência de atualizar o coreutils no OSX:

brew install coreutils
alias ls='/usr/local/bin/gls --color -h --group-directories-first'
    
por 16.02.2010 / 14:47
16

Para usuários de Mac coreutils :

brew install coreutils

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

Assumindo que seu sistema está pronto para o homebrew :

    
por 13.06.2014 / 19:01
6

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

Você pode simplesmente tentar:

ls -al | sort -k1 -r

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

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

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

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

    
por 16.02.2010 / 15:28
5

Para a resposta de delerious010 , gostaria de acrescentar que se você quiser ordenar o estilo antigo:

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

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

Isso dará algo parecido com:

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

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

    
por 16.02.2010 / 15:56
4

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ório:

  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, pois opções convenientes como --group-directories-first não funcionam no Git Bash para Windows

Depois de muito hacking, 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 produzir cada segmento da listagem de diretórios para o meu gosto e, em seguida, reuni-los usando o operador && .

  • ls -dlF --color * .* | head -n2 - extrair ./ e ../ . Não queremos passar esses dados por sort porque eles já estão na ordem correta e classificá-los pode resultar em ../ sendo listado primeiro. A opção -d é livrar-se da linha "total"; Eu gosto de adicionar -F para mostrar a barra final para diretórios (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 ( d option) e caractere ( f option). 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 LC_ALL=C locale para que (1) a saída seja consistente em shells Unix e (2) você possa ver um desempenho mais rápido, pois não tem mais a sobrecarga do pesado conjunto de caracteres UTF-8 para lidar.

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

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

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

  • find -maxdepth 1 -type l | wc -l - Obtenha 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.

  • 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 dir alias 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:

$ 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 listagens 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, por isso atualizei para esse 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"}'

Exemplo 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 é compatível com --group-directories-first , não precisamos mais recorrer a sort . Embora o novo alias não exiba tanta informação quanto o alias anterior, os ganhos de desempenho valem mais do que isso. Como um bônus, você também ganha cores!

    
por 24.10.2015 / 22:07
2

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

function lss
{
    # Shows directory listing with directories at the top.

    command ls  --color=always $@ | egrep '^d|total'
    command ls  --color=always $@ | egrep -v '^d|total';
}
    
por 16.02.2010 / 14:37
1

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"
    
por 08.06.2012 / 11:57
1

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
    
por 16.02.2010 / 14:31
1

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, sobrescrevo o comportamento padrão de ls :

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

% estendidoll

Em seguida, escrevo uma função que contém a lógica de classificação. Para cada ls , passo todos os argumentos originalmente passados 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 de arquivo regulares 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, 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 alias invocando \ls .

alias ll=list_sorted

Notas

  • Eu uso ; em vez de && como um delimitador para os comandos. Caso contrário, não será possível listar o conteúdo de diretórios que não contenham diretórios (o primeiro comando ls será avaliado como false, não permitindo a execução do próximo comando, pois está associado a && . ; evita isso.)
por 22.06.2017 / 08:43
0

Esta é uma solução de script. Lista apenas os nomes, sem dados de 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 > 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[@]}"

A saída para a última é semelhante à 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

Lembre-se de não aliasar ou alterar o comportamento padrão de ls desde que esse script o chama.

    
por 30.07.2014 / 00:37