Respostas:
ls
lista os arquivos e o conteúdo dos diretórios que estão sendo transmitidos como argumentos e, se nenhum argumento for fornecido, ele lista o diretório atual. Também podem ser passadas várias opções que afetam seu comportamento (consulte man ls
para detalhes).
Se ls
estiver sendo passado um argumento chamado *
, ele procurará um arquivo ou diretório chamado *
no diretório atual e o listará como qualquer outro. ls
não trata o *
personagem de nenhuma outra maneira que qualquer outra.
No entanto, se ls *
houver uma linha de comando do shell , o shell o expandirá de *
acordo com as regras de globbing do shell correspondente (também conhecidas como Geração de nome do arquivo ou Expansão do nome do arquivo ).
Enquanto diferentes invólucros suportam diferentes operadores de globos, a maioria deles concorda com o mais simples *
. *
como padrão significa qualquer número de caracteres; assim *
, a glob
será expandido para a lista de arquivos nos diretórios atuais que correspondem a esse padrão. Há uma exceção, no entanto, que um .
caractere de ponto ( ) inicial em um nome de arquivo deve ser correspondido explicitamente; portanto, ele *
se expande para a lista de arquivos e diretórios que não começam .
(em ordem lexicográfica).
Por exemplo, se o diretório atual contém os arquivos chamados .
, ..
, .foo
, -l
e foo bar
, *
será expandida pelo shell de dois argumentos para passar para ls
: -l
e foo bar
, por isso vai ser como se você tivesse digitado:
ls -l "foo bar"
ou
'ls' "-l" foo\ bar
Quais são as três maneiras de executar exatamente o mesmo comando. Nos 3 casos, o ls
comando (que provavelmente será executado a partir /bin/ls
de uma pesquisa nos diretórios mencionados em $PATH
) receberá esses 3 argumentos: "ls", "-l" e "foo bar".
Aliás, neste caso, ls
tratará o primeiro (estritamente falando segundo ) como uma opção.
Agora, como eu disse, conchas diferentes têm operadores de globbing diferentes. Algumas décadas atrás, zsh
introduziu o **/
operador¹, que significa corresponder a qualquer nível de subdiretórios, abreviação (*/)#
e ***/
que é o mesmo, exceto pelo fato de seguir links simbólicos ao descer os diretórios.
Alguns anos atrás (julho de 2003 ksh93o+
), ksh93
decidiu copiar esse comportamento, mas decidiu torná-lo opcional, e apenas cobriu o **
caso (não ***
). Além disso, enquanto **
sozinho não era especial zsh
(apenas significava o mesmo que *
em outros shells tradicionais, pois **
significa qualquer número de caracteres seguido por qualquer número de caracteres), em ksh93, **
significava o mesmo que **/*
(portanto, qualquer arquivo ou diretório abaixo do atual (excluindo arquivos ocultos).
bash
copiado ksh93
alguns anos mais tarde (fevereiro de 2009, bash 4.0), com a mesma sintaxe, mas com uma diferença infeliz: o bash **
era como zsh
o ***
que é, seguia links simbólicos ao retornar para subdiretórios, o que geralmente não é o que você quer fazer e pode ter efeitos colaterais desagradáveis. Foi parcialmente corrigido no bash-4.3, em que os links simbólicos ainda eram seguidos, mas a recursão parou por aí. Foi totalmente corrigido no 5.0.
yash
adicionado **
na versão 2.0 em 2008, ativado com a extended-glob
opção Sua implementação está mais próxima do zsh
que, por **
si só, não é especial. Na versão 2.15 (2009), adicionou ***
como em zsh
e duas de suas próprias extensões: .**
e .***
incluir diretórios ocultos ao repetir (em zsh
, o D
qualificador glob (como em **/*(D)
) considerará arquivos e diretórios ocultos, mas se você quiser apenas atravessar objetos ocultos dirs, mas não expandir arquivos ocultos, você precisa ((*|.*)/)#*
ou **/[^.]*(D)
).
A casca do peixe também suporta **
. Como na versão anterior bash
, segue links simbólicos ao descer a árvore de diretórios. Nesse shell, no entanto, **/*
não é o mesmo que **
. **
é mais uma extensão do *
que pode abranger vários diretórios. Em fish
, **/*.c
corresponderá, a/b/c.c
mas não a.c
, enquanto a**.c
corresponderá a.c
e ab/c/d.c
e zsh
, **/.*
por exemplo, deve ser escrito .* **/.*
. Lá, ***
é entendido como **
seguido por *
então o mesmo que **
.
tcsh
também adicionou uma globstar
opção na V6.17.01 (maio de 2010) e suporta ambos **
e ***
à la zsh
.
Assim, em tcsh
, bash
e ksh93
, (quando a opção correspondente está habilitado ( globstar
)) ou fish
, **
se expande todos os arquivos e diretórios abaixo do atual, e ***
é o mesmo que **
para fish
, um link simbólico atravessando **
para tcsh
com globstar
, e o mesmo que *
no bash
e ksh93
(apesar de ser não é impossível que versões futuras desses shells também atravessem links simbólicos).
Acima, você notou a necessidade de garantir que nenhuma das expansões seja interpretada como uma opção. Para isso, você faria:
ls -- *
Ou:
ls ./*
Existem alguns comandos (não importa ls
) onde o segundo é preferível, pois mesmo com --
alguns nomes de arquivos podem ser tratados especialmente. É o caso de -
para a maioria dos utilitários de texto, cd
e pushd
e nomes de arquivos que contenham o =
caractere para awk
por exemplo. Anexar ./
a todos os argumentos remove seu significado especial (pelo menos nos casos mencionados acima).
Também deve-se observar que a maioria dos shells possui várias opções que afetam o comportamento de globbing (como arquivos de ponto são ignorados ou não, a ordem de classificação, o que fazer se não houver correspondência ...), consulte também o $FIGNORE
parâmetro emksh
Além disso, em todos os shell mas csh
, tcsh
, fish
e zsh
, se o padrão de englobamento não corresponde a qualquer arquivo, o padrão é passado como um argumento não expandidas, que causa confusão e possivelmente bugs. Por exemplo, se não houver arquivo não oculto no diretório atual
ls *
Na verdade, chamará ls
com os dois argumentos ls
e *
. E como não há nenhum arquivo, também não foi chamado *
, você verá uma mensagem de erro de ls (não do shell) como:, ls: cannot access *: No such file or directory
que é conhecida por fazer as pessoas pensarem que era isso ls
que estava realmente expandindo os globs.
O problema é ainda pior em casos como:
rm -- *.[ab]
Se não há *.a
nem *.b
arquivo no diretório atual, então você pode acabar a exclusão de um arquivo chamado *.[ab]
por engano ( csh
, tcsh
e zsh
iria relatar um páreo erro e não chamaria rm
(e fish
não suporta os [...]
wildcards)).
Se você deseja passar um literal *
para ls
, é necessário citar esse *
caractere de alguma forma, como em ls \*
ou ls '*'
ou ls "*"
. Em shells do tipo POSIX, o globbing pode ser totalmente desabilitado usando set -o noglob
ou set -f
(o último não funciona a zsh
menos que seja em sh
/ ksh
emulado).
¹ Embora (*/)#
sempre tenha sido suportado, ele foi o primeiro em short-handed, como ..../
no zsh-2.0 (e potencialmente antes), depois ****/
no 2.1 antes de obter sua forma definitiva **/
no 2.2 (início de 1992)
find -name *
. Especialmente com padrões mais complexos, se houver exatamente uma correspondência no diretório atual, as pessoas geralmente não perceberão que não estão passando o asterisco find
.
*.[ab]
tentaria excluir tudo que termina com .[ab]
. [
não é especial em peixes.
O comando ls
padrão é ls .
: Listar todas as entradas no diretório atual .
O comando ls *
significa 'executar sl na expansão do *
padrão de shell'
O *
padrão é processado pelo shell e se expande para todas as entradas no diretório atual, exceto aquelas que começam com a .
. Irá um nível profundo.
A interpretação de *
padrões duplos ou triplos depende da casca real usada.
*
é um curinga que corresponde a 0 ou mais caracteres. Algumas conchas modernas serão recursivas em subdiretórios ao ver o **
padrão.
*
fazer acrescentar algo, veja a outra resposta explicando a globstar. Também deve ficar claro que ls não tem nada a ver com os asteriscos, nunca passou por nenhum desses asteriscos. Corra echo ls *
para ver o que seria executado quando você escrever ls *
.
Você pode desmistificar todo o processo digitando em echo
vez de ls
primeiro, para ver o que o comando se expande:
$ echo *
Applications Downloads Documents tmp.html
Portanto, neste caso, ls *
expande parals Applications Downloads Documents tmp.html
$ echo **
Applications Downloads Documents tmp.html
$ echo ***
Applications Downloads Documents tmp.html
Portanto, nenhuma mudança. Isso pressupõe que você esteja usando bash
como seu shell - a maioria das pessoas e conchas diferentes têm um comportamento diferente. Se você estiver usando ash
ou csh
ou ksh
ou zsh
, poderá esperar que as coisas funcionem de maneira diferente. Esse é o ponto de ter conchas diferentes.
Então, vamos tentar algo diferente (ainda com bash
) para que possamos ter uma idéia do que o *
operador globbing ( ) pode fazer por nós. Por exemplo, podemos filtrar por parte do nome:
$ echo D*
Downloads Documents
E, curiosamente, uma barra final é uma parte implícita de qualquer nome de diretório. Portanto */
, produzirá apenas os diretórios (e links simbólicos para os diretórios):
$ echo */
Applications/ Downloads/ Documents/
E podemos filtrar em vários níveis colocando barras no meio:
$ echo D*/*/
Documents/Work/ /Documents/unfinished/
Como o Downloads
diretório não contém subdiretórios, ele não termina na saída. Isso é muito útil apenas para examinar os arquivos que você deseja. Eu uso comandos como este o tempo todo:
$ ls -l /home/*/public_html/wp-config.php
Isso lista, se houver, todos os wp-config.php
arquivos que existem no nível base do public_html
diretório de qualquer usuário . Ou talvez para ser mais completo:
$ find /home/*/public_html/ -name wp-config.php
Ele encontrará todos os wp-config.php
arquivos nos public_html
diretórios de qualquer usuário ou em seus subdiretórios, mas operará com mais eficiência do que apenas find /home/ -name wp-config.php
porque não examinará nada além dos public_html
diretórios de cada usuário.
bash
como seu shell" ← e que a globstar não está ativada. shopt -s globstar
e tente novamente ...
set -x
que começará a imprimir o comando "real" executado a cada vez (desligue com set +x
).
Em algumas shells, incluindo o bash 4.x com a globstar
opção ativada, **
será executado um globo recursivo, diretórios correspondentes descendentes. Asteriscos adicionais não modificam mais esta operação.
ksh93
e atravessa links simbólicos na recursão que geralmente é indesejável. zsh
bash
Se você quiser "mergulhar fundo", use a opção ls -R (recursive) ou use find, da seguinte maneira:
find . -ls
"find" irá mergulhar na parte inferior da árvore de diretórios (como será 'ls -R') e possui muitas outras opções, como listar diretórios (-type d), somente arquivos (-type f) ou mostrar arquivos com outras características (nenhum usuário em / etc / passwd, permissões específicas e muito mais). O "find" também é um pouco mais seguro nos scripts (devido a regras inconsistentes de globbing entre shells, bem como escapes especiais para arquivos com traços, etc).
globbing de curinga shell não funcionará apenas com um asterisco '*' nos arquivos de ponto. Para listar apenas arquivos de ponto, use:
ls .??*
Extra * não adiciona nível de profundidade. Mas se você tentar
ls */*/*
- você receberá uma lista de subpastas de subpastas em pastas na pasta atual ...
*
s extras adicionam nível de profundidade.
bash
com a opção globstar, o korn shell e o zsh. E possivelmente outros, eu acho. unix.stackexchange.com/a/62665/14831
Minha principal preocupação é que echo ** / *. Ext geralmente ...
Pode ou não: lista um arquivo .ext no diretório atual
Pode ou não: incluir arquivos. *. Ext
Geralmente, eu preferiria que a expressão glob fosse '** /' e que pode resultar em uma string nula (sem subdiretório). É assim que eu converto expressões glob na entrada do programa. É claro que garanto que existem comentários explicando isso em exemplos de uso.