Como classificar os primeiros diretórios, arquivos, etc., ao usar "ls" no Unix

91

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

ls -la | sort -k 1

Mas eu recebi uma ordem errada.

atricapilla
fonte
é porque -vem antes dao usarsort
Nifle
4
Cabeças unix antigas (aquelas da era anterior à GUI) costumavam capitalizar seus nomes de pastas e tornar os nomes de arquivo simples sem capitalização para obter esse resultado automaticamente.
JRobert
Pergunta útil! Talvez seja hora de mudar a resposta aceita para uma que seja mais simples e que não quebre as cores dos terminais?
IPPI
Tentels -lh --group-directories-first
Diogo

Respostas:

28

O comando a seguir listará os diretórios primeiro, os arquivos comuns em segundo 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 para salvar as teclas digitadas.

Editar:

Se você deseja primeiro os diretórios e depois tudo o que não é um diretório, use o seguinte:

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

onze81
fonte
1
Este comando não listar tudo, se houver, por exemplo, sockets ou FIFO na pasta
Studer
1
Essa versão editada ainda deve funcionar com outros tipos. O primeiro grep diz tudo que começa com um 'd' e o segundo diz tudo que não começa com um 'd'. Certamente tudo começa com o anúncio ou não, certo?
Ry4an Brase
1
@ Mark - Por que não basta fazer ls -la | grep "^d" && ls -la | grep "^-" && ls -la | grep -v -E "^d|^-|^total":?
FCTW 19/08/13
1
Para fazer @ comando do FCTW um alias OSX, adicione isso ao seu ~ / .profile:alias la="ls -la | grep \"^d\" && ls -la | grep \"^-\" && ls -la | grep -E \"^d|^-\" -v | grep -v \"^total\""
aliteralmind
2
Encontrei uma notação mais curta: ls -la|grep ^d;ls -la|grep -v ^d(aspas não são necessárias e substituídas &&por ;). Outra opção é a introdução de uma variável e, em seguida, avaliá-lo: a="ls -la|grep ^d";eval $a;eval $a -v. Pode ser útil para evitar repetições quando muito mais opções são especificadas para ls/ grep. Há também essa ls -la --group-directories-firstopção, no entanto, a menor imo éls -la|sort
Steven Pribilinskiy 23/03
205

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

A minha não é tão chique no GNU Linux:

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

Dado que estou mais à vontade com meus aplicativos CLI Linux, também costumo atualizar o coreutils no OSX:

brew install coreutils
alias ls='/usr/local/bin/gls --color -h --group-directories-first'
jonathanserafini
fonte
6
infelizmente, isso não funciona no terminal osx, pois a opção - não está disponível.
MEM
7
re love: Isso é sarcasmo? Se assim for, eu concordo.
precisa saber é o seguinte
4
O objetivo do alias ls é definir os elementos de configuração que quero usar 90% do tempo. Menos pressionamentos de teclas para obter a saída desejada. Se você quiser ter saída ls nativa, poderá sempre / bin / ls.
Jonathanserafini
4
@MEM Se você estiver usando o OS X e gosta de usar o Terminal, brew install bash então deve funcionar! :)
Andrew Ashbacher
5
Minha opinião: esta deve ter sido a resposta aceita como ele lista uma opção de linha de comando para realizar exatamente o objetivo, em vez de um conjunto complicado de etc. do grep
Ryan Griggs
17

Para usuários de Mac, coreutils :

brew install coreutils

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

Supondo que seu sistema esteja pronto para homebrew :

Vadym Tyemirov
fonte
7
glsem vez. Direito?
Paul Irish
1
Sim, por padrão. Você também pode usar coreutils por padrão com PATH="/usr/local/opt/coreutils/libexec/gnubin:$PATH".
benesch
7

Há certas coisas que quero ver em uma lista de diretórios 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 diferencia maiúsculas de minúsculas
  5. A classificação ignora todos os caracteres não-alfa iniciais 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 deve ter a mesma aparência no Linux e no Windows (shell Git Bash) - essa foi a mais difícil de corrigir, pois opções convenientes como --group-directories-firstnão funcionam no Git Bash para Windows

Depois de muitos hackers, finalmente criei uma linha (embora muito longa ;-)) com a qual estou satisfeito. Eu atribuí isso a um alias 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 facilitar o gerenciamento, criei comandos separados para exibir cada segmento da lista de diretórios da minha preferência e os reuni usando o &&operador.

  • ls -dlF --color * .* | head -n2- Extraia ./e ../. Não queremos repassá-los sortporque eles já estão na ordem correta e a classificação deles pode resultar na ../listagem primeiro. A -dopção é se livrar da linha "total"; Eu gosto de adicionar -Fpara mostrar a barra final dos diretórios (ele também marcará links simbólicos com "@" quando você fizer um simples ls -F).

  • ls -AlF | LC_ALL=C grep "^d" | LC_ALL=C sort -k 9df- Extraia os diretórios e os ordene por nome de arquivo (coluna 9), ignorando os caracteres não-alfa / espaço ( dopção) e os caracteres ( fopção). A ls -Aopção exclui ./e ../da listagem, pois já as extraímos na etapa anterior. Eu costumo prefixar todos os comandos grepe sortcom a LC_ALL=Credefinição local para que (1) a saída seja consistente entre os shells do Unix e (2) às vezes você possa ver um desempenho mais rápido, já que não possui mais a sobrecarga do pesado caractere UTF-8 definido como Lide com.

  • 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- 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 - Extraia o tamanho total de todos os subdiretórios no formato legível por humanos.

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

Vamos ver o nosso novo dirapelido 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 desvantagem menor é que você não pode ter listas coloridas, pois os caracteres de controle de cores que cercam os nomes dos arquivos tornam a classificação muito pouco confiável.


ATUALIZAR

O alias acima era dolorosamente lento quando executado a partir do diretório raiz de um sistema de arquivos profundo, por isso 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"}'

Saída de amostra:

$ 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 voltar a usá-lo sort. Mesmo que o novo alias não exiba tanta informação quanto o alias anterior, os ganhos de desempenho valem a pena. Como vantagem, você também recebe cores!

thdoan
fonte
Ótima resposta! Mas quando você diz: “Depois de muita invasão, finalmente criei uma linha…” Sim, na verdade, essa não é realmente uma “linha única” no sentido clássico. Pode fazer sentido usar essa lógica e torná-la um script de shell independente e apenas executá-la ou chamá-la como um alias.
JakeGould
@JakeGould Você é rápido! Ainda nem terminei de ler a minha resposta e você já terminou de ler e disparou um comentário :). Sim, é o candidato principal para uma função, mas eu era muito preguiçoso na época, então joguei no meu arquivo .bash_aliases. Por outro lado, eu normalmente escrevo apenas uma função quando não posso fazer algo sem passar parâmetros.
Thdan
@ 10basetom: Pergunta rápida: Como você obtém as cores diferentes para as colunas em ls? Posso colorir nomes de arquivos por tipo de arquivo usando ls --color, mas não vejo uma maneira de obter essas cores úteis para as colunas. Qual o segredo?
Pirx
@Pirx Eu acredito que as colunas são coloridas pela sintaxe padrão do Stack Exchange, destacando :-).
Thdan #
Sim, isso parece ser o caso, mas é uma ótima idéia, e as soluções estão em ;-)
Pirx
6

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

Você pode simplesmente tentar:

ls -al | ordenar -k1 -r

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

ls -al | classificação -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 | -]"

Studer
fonte
1
Esta é uma solução IMO mais agradável. Usar vários processos e tubulações para classificar em vez de tubulação para classificar parece meio atrasado. Especialmente porque ls- al|sort -k1 -rfunciona. O que estava faltando é apenas a -rbandeira.
Brice
@brice O que mais me incomoda com 'classificação' é isso ./e ../não serão as duas primeiras linhas, nessa ordem. Fora isso, concordo que é a solução mais eficiente.
thdoan
Como colorir a saída?
Danijel
5

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

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

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

Isso dará algo semelhante a:

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

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

Dennis Williamson
fonte
2

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 criei e estou usando agora:

função lss
{
    # Mostra a listagem de diretórios com os diretórios na parte superior.

    comando ls --color = sempre $ @ | egrep '^ d | total'
    comando ls --color = sempre $ @ | egrep -v '^ d | total';
}
SuperMagic
fonte
Apenas um ano, isso não parece funcionar. Você precisa usar o formato de listagem longa ( ls -l) para filtrar por tipo de arquivo assim. Além disso, este comando será interrompido nos espaços (no bash). Você precisa citar da seguinte maneira: "$@"Se você quiser usar essa abordagem, poderá fazer algo assim:function lss {local temp="$(command ls -l --color=always "$@")"; egrep --color=never '^d|total' <<<"$temp"; egrep --color=never -v '^d|total' <<<"$temp"}
Six
2

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

Opções longas:

ls
    -l    # List
    --all
    -X    # Sort alphabetically by entry extension
Bobby
fonte
Isso só funcionaria se você tivesse certeza absoluta de que todos os diretórios não tinham pontos em seu nome.
Eleven81
1

Outra maneira ...

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

OU

ls -la | sort -r

OU

d=`find . -type d -d 1`;f=`find . -type f -d 1`; echo -e -DIRS- "\n$d\n" -FILES- "\n$f"
Eddie B
fonte
O que eles fazem? Onde você aprendeu a digitá-los?
Tamara Wijsman
Bem, meu sistema operacional preferido é o Debian Linux. A versão do pacote Debian gnu core utils do ls suporta a opção --show-directory-first ... quando comecei a usar o OSX, simplesmente peguei todos os meus arquivos bash dot da minha caixa Debian e os soltei no meu diretório home ... tinha um monte de bash_aliases que quebrou assim ... foi então que eu tinha que descobrir algumas soluções alternativas para os meus aliases ...
Eddie B
O primeiro é um pouco redundante ... Não há realmente nenhuma razão para classificar os diretórios, pois é a ordem que precisamos modificar, não os diretórios ... o 'ls -la | sort -r 'é o que realmente funciona. Basicamente, está declarando ... 1) A) Encontre. -d 1 -type d (Comece neste diretório, pesquise uma profundidade de diretório e pesquise apenas diretórios) B) ls -la (liste todos os atributos de arquivos) C) Classifique-os ao contrário 2) Faça como 1) apenas solte a localização. .. não é necessário ... Eu realmente gosto solução Studers' melhor ... :-)
Eddie B
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

Antes de tudo, substituo o comportamento padrão para ls:

  • -l: Sempre exiba a lista como uma lista vertical unidimensional
  • -h: Exibe tamanhos de arquivo legíveis 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'

Estendido ll

Em seguida, escrevo uma função que contém a lógica de classificação. Para cada um deles ls, passo quaisquer argumentos passados ​​originalmente para ele. Isso me permite usar o alias de um diretório de trabalho diferente daquele que eu quero listar (ou seja ls -a ~).

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

Por fim, mostro tudo o que não é um diretório nem um arquivo (nem a linha que mostra o tamanho total do conteúdo do diretório). Isso é feito grepping diretamente, entradas regulares de arquivos e a entrada total e, em seguida, invertendo o resultado por meio do -vargumento

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 lscaso minha função seja interrompida em alguns cenários. Então eu quero poder usar ls. Como alternativa, você sempre pode chamar o lscomando 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 será possível listar o conteúdo de diretórios que não contêm diretórios (o primeiro comando ls é avaliado como falso, não permitindo a execução do próximo comando, pois ele é acoplado a &&. ;Evita isso.)
Kleinfreund
fonte
0

Esta é uma solução de script. Lista apenas os nomes, sem dados do inode, alfabéticos, sem distinção entre maiúsculas e minúsculas, formatados em colunas. Embora seja maior de linha em vez de maior de coluna, 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 do ú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

Lembre-se de não usar o alias ou alterar o comportamento padrão de ls, pois esse script o chama.

Igorio
fonte