Meu sistema:
- SO: MacOS/Mac OS X (Mojave 10.14.5)
- Núcleo do sistema operacional: Darwin (18.6.0)
- Kernel: Kernel Darwin/XNU (18.6.0/xnu-4903.261.4~2/RELEASE_X86_64)
- ls: versão desconhecida, mas
man ls
fornece uma página do Manual de Comandos Gerais do BSD - Cartuchos:
- Bash: GNU bash, versão 5.0.7(1)-release (x86_64-apple-darwin18.5.0)
- Zsh: zsh 5.7.1 (x86_64-apple-darwin18.2.0)
No MacOS, em um terminal CLI usando um shell como bash ou zsh, gostaria de usar o comando (BSD) ls
(ou talvez uma ferramenta igualmente comum e útil) para listar o conteúdo de um diretório diferente do diretório de trabalho atual , onde todos os arquivos, exceto aqueles que terminam com um til ( ~
), são mostrados.
Excluindo a última estipulação, ls
naturalmente realiza esta tarefa quando o diretório não atual é usado como argumento para ls
: ls arg
onde arg
é um caminho absoluto ou relativo para o diretório não atual (como /absolute/path/to/directory
,, ~/path/from/home/to/directory
ou path/from/current/dir/to/directory
).
Eu sei como listar conteúdos que não são de backup no diretório atual, usando a expansão de nome de arquivo (também conhecida como "globbing") e a -d
opção (para listar diretórios e não seu conteúdo), assim: ls -d *[^~]
(ou ls -d *[!~]
). Quero o mesmo tipo de resultados, mas para um diretório não atual.
Quase posso conseguir o que desejo usando ls -d arg/*[^~]
, onde arg
é o mesmo descrito acima, mas os resultados mostram o caminho para cada elemento de conteúdo (ou seja, cada arquivo e diretório no diretório de interesse). Quero ls
exibir cada elemento sem o caminho para ele, como é feito com ls arg
.
No Linux, usando o comando GNU ls
, posso conseguir exatamente o que desejo usando a -B
opção de não listar arquivos de backup ls -B arg
:. Embora seja isso que eu queira, gostaria de conseguir isso usando ferramentas nativas do MacOS, de preferência o BSD ls
.
Nota: não quero usar grep
(por exemplo, ls arg | grep '.*[^~]$'
), pois grep
altera a formatação e a coloração da saída.
Recapitulação da pergunta: em um Mac, como posso listar o conteúdo de um diretório não atual, mas não os arquivos de backup, de preferência usando ls
?
Responder1
Você poderia executar ls
em um subshell:
(cd arg; ls -d *[^~])
Responder2
Usando bash
e sua GLOBIGNORE
variável shell, junto com o macOS basename
:
$ mkdir dir
$ touch dir/file{1,2}{,~}
$ ls -R
dir
./dir:
file1 file1~ file2 file2~
$ GLOBIGNORE=*~
$ ls -d dir/*
dir/file1 dir/file2
$ basename -a dir/*
file1
file2
Definir GLOBIGNORE
uma lista de :
padrões delimitados fará com que a conclusão do nome do arquivo ignore esses padrões.
O basename
utilitário no macOS aceita mais de um nome de caminho se você usar sua -a
opção e retornará uma lista que consiste apenas nas partes do nome de arquivo desses nomes de caminho.
Em vez de usar GLOBIGNORE
(que fornece uma maneira mais genérica de ignorar certas expansões de padrão de nome de arquivo), você poderia obviamente usar seu padrão *[!~]
(observe que !
nega uma classe de caracteres no shell, enquanto ^
nega uma classe de caracteres em expressões regulares):
unset GLOBIGNORE
basename -a dir/*[!~]
... ou você pode simplesmente instalar GNU coreutils do Homebrew e usar gls -B
como está acostumado em sistemas Linux.
Responder3
A resposta concisa é usar um subshell para executar o comando no diretório não atual:
(cd arg; ls -d *[^~])
Mas para criar uma função geral que funcione tanto para o diretório atual quanto para qualquer diretório não atual, podemos adicionar o seguinte a .bashrc
(ou a bashrc_aliases_lsBSD
, originado por .bashrc
):
alias ls='/bin/ls'
alias l=''
unalias l
function l () { ( if [[ -n "$@" ]]; then cd "$@"; fi ; /bin/ls -d *[^~] ) }
Se desafiarmos a preferência mencionada acima para usar o BSD, podemos usar o GNU ls
sem problemas instalando os utilitários principais do GNU (por exemplo, via brew install coreutils
) e criando os aliases desejados (em vez de usar o código acima) em .bashrc
(ou em bashrc_aliases_lsGNU
, originado por .bashrc
) :
alias ls='/usr/local/bin/gls'
alias l='/usr/local/bin/gls -B'
Minha própria solução atual é usar essas duas construções e alternar entre elas quando desejado usando uma variável que eu chamo LS_TYPE
e uma função que eu chamo ls-switch
(definida em bashrc_aliases
, originada por .bashrc
), que origina um dos dois arquivos de configuração contendo essas duas construções:
function ls-switch () {
if [[ $LS_TYPE = "GNU" ]] ; then
LS_TYPE="BSD"
source ~/.config/bash/bashrc_aliases_lsBSD
elif [[ $LS_TYPE = "BSD" ]] ; then
LS_TYPE="GNU"
source ~/.config/bash/bashrc_aliases_lsGNU
fi
}
Com esse arranjo, os comportamentos padrão de ls
e l
são definidos .bashrc
com a primeira definição LS_TYPE
e escolha de qual arquivo de configuração será originado, por exemplo:
LS_TYPE="BSD"
source ~/.config/bash/bashrc_aliases_lsBSD