Globbing e Wildcards: Correspondência de Padrões de Arquivos no Linux
O que você vai conseguir fazer
- Usar os três símbolos básicos `*`, `?` e `[]` na situação certa
- Explicar que quem expande um glob é o shell, e não o comando
- Evitar as armadilhas do caso sem correspondência, dos arquivos ocultos e das aspas
Pré-requisitos (leia estes primeiro)
O Que Você Vai Aprender
- Que globbing (wildcards) é um trabalho feito pelo shellUm programa interativo que interpreta os comandos digitados e os executa., não pelo comando
- Como usar os três símbolos básicos
*,?e[] - Como a expansão de chaves
{}é diferente - Como evitar armadilhas com
extglob, arquivos ocultos e o caso sem correspondência
As palavras usadas aqui (organizadas antes)
- Glob: uma forma de indicar vários arquivos de uma vez. Wildcard e padrão querem dizer quase a mesma coisa. Este artigo usa sempre "glob".
- Expressão regular: uma forma de buscar dentro de um texto. O
grepusa isso. É um mecanismo diferente do glob. Os símbolos se parecem, e é justamente por isso que as pessoas confundem. - Expansão: o shell trocando os símbolos que você escreveu por nomes de arquivo reais.
- Arquivo oculto: um arquivo cujo nome começa com
.. O exemplo clássico é o.bashrc.
No glob, o * significa "qualquer quantidade de caracteres". Na expressão regular, ele significa "repita o caractere anterior". Mesmo símbolo, sentido diferente.
Resumo Rápido
- Qualquer caractere, qualquer quantidade ->
*(ex.:*.txt) - Exatamente um caractere ->
?(ex.:file?.log) - Um caractere de um conjunto ->
[](ex.:img[0-9].png) - O shell expande o padrão, não o comando
1. O Que é Globbing?
Conclusão: O shell expande wildcards em nomes de arquivo antes do comando executar.
ls *.txt, só os arquivos .txt aparecem. O que aquele * significa?* é o símbolo para "qualquer caractere, qualquer número de vezes".* é o shell, e não o ls.ls?*.txt. Ele reescreve isso nos nomes de arquivo que realmente existem e entrega ao ls. Chamamos isso de expansão de glob.Como a expansão funciona
Se o diretórioUm local que organiza arquivos. É a mesma ideia da "pasta" do Windows ou macOS. atual tem a.txt, b.txt e memo.md:
Voce digita: ls *.txt Shell expande: ls a.txt b.txt <- memo.md e excluido ls recebe: a.txt b.txt
ls não sabe nada sobre *. Ele apenas recebe os nomes de arquivo expandidos.
O globbing trabalha com nomes de arquivo. As expressões regulares buscam dentro de um texto, e o .* do grep é uma delas. São mecanismos diferentes. Não confunda os dois.
Primeiro, sobre evitar acidentes
O glob é poderoso junto com o rm. Ele também é perigoso. Um arquivo removido com rm não vai para a lixeira como acontece na interface gráfica. Ele some na hora.
Então crie o hábito de conferir o mesmo padrão com o ls antes de executar o rm.
$ ls *.tmp # veja com os proprios olhos o que o padrao abrange $ rm *.tmp # remova so depois de ficar convencido
O terminal virtual deste site é para prática. Nada do que você digitar lá apaga um arquivo do seu computador, então experimente à vontade.
2. O Asterisco *: Qualquer String
Conclusão: O
*corresponde a zero ou mais caracteres, mas nunca a um ponto inicial.
$ ls
a.txt b.txt data.csv report.txt notes.md
# Apenas arquivos terminando em .txt $ ls *.txt
a.txt b.txt report.txt
*.txt significa "algo + .txt".* também corresponde a zero caracteres. Então * sozinho significa "tudo".re*?report.txt corresponde. Você pode colocar o * no início, no fim ou no meio.# Comeca com re $ ls re* report.txt # Contem data (qualquer coisa antes ou depois esta ok) $ ls *data*
data.csv
O * não corresponde a um ponto no início, ou seja, os arquivos ocultos ficam de fora.
Executar ls * não mostra um arquivo como o .bashrc. Essa regra existe para impedir que um rm * leve junto os seus arquivos de configuração sem querer.
3. O Ponto de Interrogação ?: Qualquer Caractere Único
Conclusão: O
?corresponde a exatamente um caractere, para nomes de comprimento fixo.
$ ls
log1.txt log10.txt log2.txt log3.txt
# log + um caractere + .txt (log10.txt e excluido: dois caracteres) $ ls log?.txt
log1.txt log2.txt log3.txt
? é apenas um caractere. Por que o log10.txt ficou de fora?log?.txt significa "log, depois exatamente um caractere, depois .txt".log10.txt tem dois caracteres ali, 1 e 0. Por isso não corresponde.??. Então log??.txt corresponde ao log10.txt.# Dois caracteres $ ls log??.txt
log10.txt
4. Os Colchetes []: Um Caractere de um Conjunto
Conclusão: O
[]corresponde a um caractere do conjunto, com intervalos e negação.
$ ls
img0.png img1.png img2.png img9.png imgA.png
4-1. Listar os candidatos
# 0, 1 ou 2 $ ls img[012].png
img0.png img1.png img2.png
4-2. Usar um intervalo
# Um digito de 0-9 $ ls img[0-9].png
img0.png img1.png img2.png img9.png
[0-9] significa "0 até 9". Posso fazer com letras também?[a-z] para minúsculas e [A-Z] para maiúsculas. Você também pode combinar, como em [a-zA-Z0-9].4-3. Negar (! ou ^)
# Um caractere que NAO e um digito $ ls img[!0-9].png
imgA.png
Referência de sintaxe []
| Sintaxe | Significado |
|---|---|
[abc] |
Um entre a / b / c |
[a-z] |
Um caractere a-z (intervalo) |
[0-9] |
Um caractere 0-9 (intervalo) |
[!0-9] |
Um caractere não-dígito (negação) |
[a-zA-Z] |
Uma letra (intervalos combinados) |
5. Expansão de Chaves {}: Um Mecanismo Separado
Conclusão: A expansão de chaves constrói strings independentemente da existência dos arquivos.
# Expansao de chaves: gera tres strings
$ echo file{1,2,3}.txtfile1.txt file2.txt file3.txt
{} apenas constrói textos e não verifica se os arquivos existem.{} como "criar vários de uma vez" e no * ou [] como "escolher entre o que já existe".# Criar diretorios numerados de uma vez (nao precisam existir)
$ mkdir log{2024,2025,2026}
# Um intervalo numerico tambem funciona
$ echo {1..5}1 2 3 4 5
Quando * ou [] não correspondem a nenhum arquivo, o padrão fica como texto simples. Esse é o comportamento padrão do bash.
Já a expansão de chaves {} acontece sempre. Os dois se comportam de forma diferente, então tenha cuidado.
6. extglob: Globbing Estendido para Mais Poder
Conclusão: extglob habilita padrões avançados; está desabilitado por padrão.
# Habilitar globbing estendido (bash) $ shopt -s extglob
@(...) para "qualquer um de" e !(...) para "exceto".Sintaxe do extglob
| Sintaxe | Significado |
|---|---|
?(pattern) |
Zero ou uma ocorrência |
*(pattern) |
Zero ou mais ocorrências |
+(pattern) |
Uma ou mais ocorrências |
@(pattern) |
Exatamente uma (qualquer uma de) |
!(pattern) |
Qualquer coisa exceto o padrão |
Dentro de pattern, separe as alternativas com |.
# Corresponder .jpg ou .png $ ls *.@(jpg|png) # Tudo exceto .txt $ ls !(*.txt)
O shopt -s extglob vale apenas para aquele shell. Feche o terminal e ele se perde.
Para desligar agora, execute shopt -u extglob.
Para ter isso sempre, adicione a linha ao seu ~/.bashrc. Isso mexe em um arquivo de configuração, então copie-o antes.
$ cp ~/.bashrc ~/.bashrc.bak $ echo 'shopt -s extglob' >> ~/.bashrc $ source ~/.bashrc
Se algo der errado, cp ~/.bashrc.bak ~/.bashrc restaura tudo. O >> adiciona ao final do arquivo; um > sozinho apagaria tudo, por isso não é usado aqui.
7. Armadilhas Comuns para Iniciantes
Conclusão: Comportamento sem correspondência, arquivos ocultos e aspasEnvolver um texto entre aspas (' ou ") para que seja tratado como um único valor, por exemplo um que tenha espaços. são as armadilhas clássicas.
7-1. Lina se atrapalha: sem correspondência, o padrão fica como está
# Quando nao ha arquivos .xml $ ls *.xml
ls: cannot access '*.xml': No such file or directory
*.xml sem mudar nada. O * parou de funcionar?ls respondeu que não existe arquivo com esse nome.shopt -s nullglob muda isso para não repassar nada quando houver zero correspondências.7-2. * não captura arquivos ocultos
# Para incluir arquivos ocultos $ shopt -s dotglob $ ls *
Com o dotglob habilitado, o * também corresponde a arquivos ocultos. Mantê-lo desabilitado é mais seguro no dia a dia.
7-3. Aspas desabilitam globbing
# Aspas impedem * de expandir $ ls "*.txt"
ls: cannot access '*.txt': No such file or directory
Envolver um padrão em aspas, como "*.txt" ou '*.txt', impede a expansão de glob.
Isso é útil quando você quer o * como caractere comum. Mas, se a intenção era expandir, as aspas desligam tudo sem avisar.
8. Mini Exercícios: Tente Você Mesmo
Conclusão: Três tarefas sobre extensões, comprimento e intervalos para praticar globbing.
Trabalhe dentro de um diretório vazio novo. Assim nenhum dos seus arquivos existentes é tocado.
# Preparar um diretorio e arquivos de pratica $ mkdir -p ~/glob-practice && cd ~/glob-practice $ touch a.txt b.txt c.log data1.csv data2.csv data10.csv
Exercício 1: Liste apenas os arquivos terminados em .csv.
Ver Dica 1 (Direção)
Diga "o início do nome pode ser qualquer coisa, mas o fim precisa ser .csv". Um símbolo cobre esse início.
Ver Dica 2 (Nome do comando)
Liste com ls. O símbolo para "qualquer quantidade de caracteres" é *.
Ver Resposta
$ ls *.csv
data1.csv data10.csv data2.csv
Aparecem os três nomes terminados em .csv. O a.txt e o c.log ficam de fora.
Repare que o ls ordena os nomes como texto. Por isso o data10.csv vem antes do data2.csv.
Exercício 2: Liste apenas data + um caractere + .csv. Deixe o data10.csv de fora.
Ver Dica 1 (Direção)
Desta vez o comprimento é fixo. Use o símbolo de "exatamente um caractere" em vez do de "qualquer quantidade".
Ver Dica 2 (Nome do comando)
Liste com ls. O símbolo para exatamente um caractere é ?.
Ver Resposta
$ ls data?.csv
data1.csv data2.csv
O data10.csv tem dois caracteres ali, 1 e 0, por isso ele cai fora.
Exercício 3: Mostre apenas data1.csv e data2.csv, usando colchetes.
Ver Dica 1 (Direção)
Liste você mesma os caracteres desejados. Use a forma que significa "um caractere deste conjunto".
Ver Dica 2 (Nome do comando)
Liste com ls. O conjunto vai dentro de []. Escreva 1 e 2 nele.
Ver Resposta
$ ls data[12].csv
data1.csv data2.csv
[12] significa "um caractere, 1 ou 2". O data10.csv fica de fora.
Quando terminar, você pode remover o diretório de prática inteiro.
O -r é a opção que significa "remover o diretório e tudo o que está dentro dele". Acrescente -i e ele pergunta item por item. Olhe o conteúdo com ls antes.
$ cd ~ $ ls ~/glob-practice $ rm -ri ~/glob-practice
9. Revisão
* é qualquer quantidade de caracteres, o ? é exatamente um e o [] escolhe um do conjunto. Anotado.rm, confira o mesmo padrão com o ls. Nunca pule esse passo.Resumo do Dia em 3 Linhas
- Quem expande um glob é o shell, e não o comando. O comando recebe os nomes já expandidos
- O
*corresponde a zero ou mais caracteres, o?a exatamente um e o[]a um do conjunto - Antes de juntar um padrão com o
rm, confira antes com ols