Como posso fazer com que o "ls" mostre os dotfiles primeiro sem ficar insensível a maiúsculas e minúsculas?

16

Crie os seguintes arquivos em um diretório.

$ touch .a .b a b A B 你好嗎

Meu pedido ls padrão ignora a presença dos pontos principais, mesclando-os com os outros arquivos.

$ ls -Al
total 0
-rw-r--r-- 1 sparhawk sparhawk 0 Jun  8 17:03 a
-rw-r--r-- 1 sparhawk sparhawk 0 Jun  8 17:03 .a
-rw-r--r-- 1 sparhawk sparhawk 0 Jun  8 17:03 A
-rw-r--r-- 1 sparhawk sparhawk 0 Jun  8 17:03 b
-rw-r--r-- 1 sparhawk sparhawk 0 Jun  8 17:03 .b
-rw-r--r-- 1 sparhawk sparhawk 0 Jun  8 17:03 B
-rw-r--r-- 1 sparhawk sparhawk 0 Jun  8 17:06 你好嗎

Eu posso change LC_COLLATE para colocar os dotfiles primeiro.

$ LC_COLLATE=C ls -Al
total 0
-rw-r--r-- 1 sparhawk sparhawk 0 Jun  8 17:03 .a
-rw-r--r-- 1 sparhawk sparhawk 0 Jun  8 17:03 .b
-rw-r--r-- 1 sparhawk sparhawk 0 Jun  8 17:03 A
-rw-r--r-- 1 sparhawk sparhawk 0 Jun  8 17:03 B
-rw-r--r-- 1 sparhawk sparhawk 0 Jun  8 17:03 a
-rw-r--r-- 1 sparhawk sparhawk 0 Jun  8 17:03 b
-rw-r--r-- 1 sparhawk sparhawk 0 Jun  8 17:06 你好嗎

Infelizmente, isso torna a ordem de classificação sensível a maiúsculas e minúsculas, ou seja, A e B precedem a e b . Existe uma maneira de imprimir os dotfiles primeiro sem permanecer insensível a maiúsculas e minúsculas ( A e a precede B e b )?

Editar: tentando modificar LC_COLLATE

Nenhuma das respostas replicou completamente a funcionalidade de ls facilmente. Concebivelmente, eu poderia envolver alguns deles em uma função, mas isso teria que incluir algum código detalhado sobre (por exemplo) como trabalhar sem argumento versus fornecer um diretório como um argumento. Ou como lidar com um sinalizador -d explícito.

Como alternativa, achei que talvez pudesse haver um LC_COLLATE melhor para usar. No entanto, não consigo fazer isso funcionar. Atualmente estou usando LC_COLLATE="en_AU.UTF-8" . Verifiquei /usr/share/i18n/locales/en_AU (embora não tenha certeza se esse é o arquivo correto, pois não consigo ver nenhuma referência a UTF-8 ); Eu encontrei o seguinte.

LC_COLLATE
copy "iso14651_t1"
END LC_COLLATE

/usr/share/i18n/locales/iso14651_t1 contém copy "iso14651_t1_common" . Finalmente, /usr/share/i18n/locales/iso14651_t1_common contém

 <U002E> IGNORE;IGNORE;IGNORE;<U002E> # 47 .

Eu excluí esta linha, executei sudo locale-gen e reiniciei meu computador. Infelizmente, isso não mudou nada.

    
por Sparhawk 08.06.2016 / 09:15

4 respostas

9

O OP estava muito próximo da edição de /usr/share/i18n/locales/iso14651_t1_common , mas o truque não é excluir a linha

<U002E> IGNORE;IGNORE;IGNORE;<U002E> # 47 .

mas para modificá-lo para

<U002E> <RES-1>;IGNORE;IGNORE;<U002E> # 47 .

Por que isso funciona

As instruções IGNORE especificam que o ponto final (aka período ou caractere <U002E> ) será ignorado ao ordenar as palavras em ordem alfabética. Para fazer seus dotfiles virem primeiro, altere IGNORE para um símbolo de intercalação que vem antes de todos os outros caracteres. Os símbolos de agrupamento são definidos por linhas como

collating-symbol <something-inside-angle-brackets>

e eles são ordenados pela aparência da linha

<something-inside-angle-brackets>

Na minha cópia de iso14651_t1_common , o símbolo de ordenação do primeiro lugar é <RES-1> , que aparece na linha 3458. Se o arquivo for diferente, use o símbolo de intercalação que for ordenado primeiro.

Detalhes sobre a ordenação de caracteres com LC_COLLATE

<U002E> tem três IGNORE declarações porque as letras podem ser comparadas várias vezes em caso de empates. Para entender isso, considere minúsculas a e maiúsculas A (que fazem parte de um grupo de caracteres que realmente são comparados quatro vezes):

<U0061> <a>;<BAS>;<MIN>;IGNORE # 198 a
<U0041> <a>;<BAS>;<CAP>;IGNORE # 517 A

Ter várias rodadas de comparação permite que os arquivos que começam com "a" e "A" sejam agrupados porque ambos são comparados como <a> durante a primeira passagem, com a próxima letra determinando a ordem. Se todas as letras a seguir forem iguais (por exemplo, a.txt e A.txt ), a terceira passagem colocará a.txt primeiro porque o símbolo de intercalação para letras minúsculas <MIN> aparece na linha 3467, antes do símbolo de intercalação para maiúsculas letras <CAP> (linha 3488).

Implementando essa alteração

Se você quiser que o período seja o primeiro todas as vezes que um programa envia cartas usando LC_COLLATE , você pode modificar iso14651_t1_common conforme descrito acima e reconstruir seu arquivo de locais. Mas se você quiser fazer essa alteração somente para ls e sem acesso root, você pode copiar os arquivos de localidade originais para outro diretório antes de modificá-los.

O que eu fiz

Meu idioma padrão é en_US, então copiei en_US , iso14651_t1 e iso14651_t1_common para $HOME/path/to/new/locales . Lá, fiz a alteração mencionada acima para iso14651_t1_common e renomei en_US para en_DOTFILE . Em seguida, eu compilei o código do idioma en_DOTFILE com

localedef -i en_DOTFILE -f UTF-8 -vc $HOME/path/to/new/locales/en_DOTFILE.UTF-8

Para substituir a ordem padrão ls , crie um script BASH chamado ls :

#!/bin/bash
LOCPATH=$HOME/path/to/new/locales LANG=en_DOTFILE.UTF-8 ls "$@"

salve-o em algum lugar que apareça antes de /usr/bin em seu caminho e torne-o executável com chmod +x ls .

    
por 24.04.2017 / 18:36
10

Você pode usar a ordem de classificação do shell (que pode não envolver a ordem de intercalação do local; bash , AT & T ksh , yash , tcsh e zsh fornecem os resultados esperados, mksh e dash não. fish parece dar uma ordem insensível a maiúsculas e minúsculas, mas dá resultados diferentes quando há caracteres não-ASCII):

ls -dUl -- .* *

Isso dá a ls uma lista explícita de arquivos (e diretórios) para listar e desativa a classificação de ls ( -U , que é uma extensão GNU).

Existem algumas ressalvas, dependendo do shell que você está usando.

  • Com zsh , a opção padrão nomatch fará com que o comando falhe se o diretório não contiver arquivos ocultos e não ocultos; você poderia desabilitar nomatch para evitar isso, mas seria melhor fazer set -o cshnullglob (e o comando falhar somente se nenhum dos globs corresponder como em (t)csh ou nos primeiros shells Unix).
  • Com a zsh , pdksh e sua derivada e fish , .* não inclui . e .. , então isso corresponde a ls -Al . Com outros shells, . e .. são incluídos, correspondendo a ls -al . No último caso, você precisaria alterar os padrões de globbing para excluir . e .. ( ls -dUl -- ..?* .[!.]* * ).
  • Exceto em fish , (t)csh ou zsh , se algum dos padrões de globbing não corresponder a nada, ls produzirá uma mensagem de erro; você pode evitar isso definindo a opção nullglob (em bash ou zsh pelo menos) ou redirecionando stderr para /dev/null ( ls -dUl -- ..?* .[!.]* * 2>/dev/null ). Se você usar nullglob , atente para o comportamento potencialmente surpreendente que causa (consulte Shell comendo caracteres '?' ). fish se comporta como bash com nomatch , exceto que, quando interativa, uma mensagem de aviso será emitida para cada glob que não tenha correspondência.

(Com agradecimentos a Stéphane Chazelas por todo o feedback!)

    
por 08.06.2016 / 09:36
4

Você pode simplesmente usar dois comandos ls separados:

$ ls -dl ..?* .[^.]* 2>/dev/null ; ls -dl *
-rw-r--r--. 1 sparhawk sparhawk 0  8 Jun  09:29 .a
-rw-r--r--. 1 sparhawk sparhawk 0  8 Jun  09:29 .b
-rw-r--r--. 1 sparhawk sparhawk 0  8 Jun  09:29 a
-rw-r--r--. 1 sparhawk sparhawk 0  8 Jun  09:29 A
-rw-r--r--. 1 sparhawk sparhawk 0  8 Jun  09:29 b
-rw-r--r--. 1 sparhawk sparhawk 0  8 Jun  09:29 B
-rw-r--r--. 1 sparhawk sparhawk 0  8 Jun  09:29 你好嗎

Diferentemente das outras respostas até agora, essa abordagem exibe os arquivos de pontos primeiro evitando as entradas . e .. e, em seguida, as entradas restantes na ordem alfabética ls .

As respostas do @StephenKitt podem ser melhoradas para alcançar o mesmo resultado:

$ ls -dUl ..?* .[^.]* * 2>/dev/null
    
por 08.06.2016 / 09:35
-2

Você pode jogar com as opções de comando ls . Tente isto:

# ls -laXr

Onde:

-l     use a long listing format
-a, --all
              do not ignore entries starting with .
-X     sort alphabetically by entry extension
-r, --reverse
              reverse order while sorting
    
por 08.06.2016 / 09:32

Tags