Globbing e Wildcards: Correspondencia de Padroes de Arquivos no Linux

Globbing e Wildcards: Correspondencia de Padroes de Arquivos no Linux

O Que Voce Vai Aprender

  • Que globbing (wildcards) e um trabalho feito pelo shell, nao pelo comando
  • Como usar os tres simbolos basicos *, ? e []
  • Como a expansao de chaves {} e diferente
  • Como evitar armadilhas com extglob, dotfiles e comportamento sem correspondencia

Resumo Rapido

  • 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 padrao, nao o comando

1. O Que e Globbing?

Conclusao: O shell expande wildcards em nomes de arquivo antes do comando executar.

Lina: Senpai, quando eu digito ls *.txt, so os arquivos .txt aparecem. O que aquele * realmente significa?
Veterano Linny: Otima pergunta. * e um wildcard que significa "qualquer caractere, qualquer numero de vezes." E aqui esta o ponto principal: e o shell, nao o ls, que processa o *.
Lina: Espera, nao e o ls?
Veterano Linny: Isso mesmo. No momento em que voce pressiona Enter, o shell olha para *.txt, reescreve nos nomes de arquivo que realmente existem, e entao passa para o ls. Chamamos isso de expansao de glob.

Como a expansao funciona

Se o diretorio 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 nao sabe nada sobre *. Ele apenas recebe os nomes de arquivo expandidos.

Globbing corresponde nomes de arquivo. E um mecanismo diferente de expressoes regulares (como .* no grep), que buscam dentro de texto. Nao os confunda.

2. O Asterisco *: Qualquer String

Conclusao: 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
Lina: Entao *.txt significa "algo + .txt"?
Veterano Linny: Exatamente. E lembre-se que * corresponde a zero caracteres tambem, entao * sozinho significa "tudo."
Lina: E o que acontece com re*?
Veterano Linny: Isso significa "comeca com re," entao report.txt corresponde. Voce pode colocar * no inicio, 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

* nao corresponde a um ponto inicial (arquivos ocultos). Executar ls * nao mostrara arquivos como .bashrc. Isso protege voce de varrer acidentalmente dotfiles (por exemplo, com rm *).

3. O Ponto de Interrogacao ?: Qualquer Caractere Unico

Conclusao: O ? corresponde a exatamente um caractere, para nomes de comprimento fixo.

$ ls
log1.txt  log2.txt  log3.txt  log10.txt
# log + um caractere + .txt (log10.txt e excluido: dois caracteres)
$ ls log?.txt
log1.txt  log2.txt  log3.txt
Lina: Entao ? e apenas um caractere. Por que log10.txt foi excluido?
Veterano Linny: Porque log?.txt significa "log, depois exatamente um caractere, depois .txt." log10.txt tem dois caracteres (1 e 0), entao nao corresponde.
Lina: E se eu quiser dois caracteres?
Veterano Linny: Basta escrever ??. Entao log??.txt corresponde a log10.txt.
# Dois caracteres
$ ls log??.txt
log10.txt

4. Os Colchetes []: Um Caractere de um Conjunto

Conclusao: O [] corresponde a um caractere do conjunto, com intervalos e negacao.

$ 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
Lina: Entao [0-9] significa "0 ate 9." Pratico. Posso fazer com letras tambem?
Veterano Linny: Claro. [a-z] para minusculas, [A-Z] para maiusculas, e voce pode combinar como [a-zA-Z0-9]. Lembre-se que sempre corresponde a exatamente um caractere.

4-3. Negar (! ou ^)

# Um caractere que NAO e um digito
$ ls img[!0-9].png
imgA.png

Referencia 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 nao-digito (negacao)
[a-zA-Z] Uma letra (intervalos combinados)

5. Expansao de Chaves {}: Um Mecanismo Separado

Conclusao: A expansao de chaves constroi strings independentemente da existencia dos arquivos.

# Expansao de chaves: gera tres strings
$ echo file{1,2,3}.txt
file1.txt file2.txt file3.txt
Lina: Espera, isso nao e a mesma coisa que globbing?
Veterano Linny: Parece similar mas e completamente diferente. {} apenas constroi strings e nao verifica se os arquivos existem. Entao produz nomes ate para arquivos que nao estao la.
Lina: Enquanto globbing so expande para arquivos que realmente existem.
Veterano Linny: Isso mesmo. Pense em {} como "crie estes de uma vez," e * ou [] como "escolha entre o que ja 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 [] nao correspondem a nenhum arquivo, o padrao e deixado como string literal (padrao do bash). A expansao de chaves {}, no entanto, e sempre expandida. O comportamento difere, entao tenha cuidado.

6. extglob: Globbing Estendido para Mais Poder

Conclusao: extglob habilita padroes avancados; esta desabilitado por padrao.

# Habilitar globbing estendido (bash)
$ shopt -s extglob
Lina: Entendi os simbolos basicos. Mas posso escrever algo como "apenas .jpg e .png"?
Veterano Linny: Com globbing padrao isso e complicado, mas se voce habilitar extglob (globbing estendido) fica muito mais facil. Use @(...) para "qualquer um de" e !(...) para "exceto."

Sintaxe do extglob

Sintaxe Significado
?(pattern) Zero ou uma ocorrencia
*(pattern) Zero ou mais ocorrencias
+(pattern) Uma ou mais ocorrencias
@(pattern) Exatamente uma (qualquer uma de)
!(pattern) Qualquer coisa exceto o padrao

Separe alternativas dentro de pattern com |.

# Corresponder .jpg ou .png
$ ls *.@(jpg|png)

# Tudo exceto .txt
$ ls !(*.txt)

shopt -s extglob se aplica apenas aquele shell. Para usar sempre, adicione ao seu ~/.bashrc. Para desabilitar, execute shopt -u extglob.

7. Armadilhas Comuns para Iniciantes

Conclusao: Comportamento sem correspondencia, arquivos ocultos e aspas sao as armadilhas classicas.

7-1. Sem correspondencia deixa o padrao como esta

# Quando nao ha arquivos .xml
$ ls *.xml
ls: cannot access '*.xml': No such file or directory
Lina: Ele esta procurando um arquivo literalmente chamado *.xml? Que erro estranho.
Veterano Linny: Por padrao, o bash deixa o padrao sem expandir quando nada corresponde, passando-o para o ls como uma string literal. Por isso ele diz que nao existe tal arquivo. Use shopt -s nullglob para expandir para nada quando houver zero correspondencias.

7-2. * nao captura arquivos ocultos

# Para incluir arquivos ocultos
$ shopt -s dotglob
$ ls *

Com dotglob habilitado, * tambem corresponde a dotfiles. Mante-lo desabilitado e mais seguro para uso cotidiano.

7-3. Aspas desabilitam globbing

# Aspas impedem * de expandir
$ ls "*.txt"
ls: cannot access '*.txt': No such file or directory

Envolver um padrao em aspas como "*.txt" ou '*.txt' impede a expansao de glob. Isso e util quando voce quer * como caractere literal, mas se voce pretendia expandir, as aspas desabilitam silenciosamente.

8. Mini Exercicios: Tente Voce Mesmo

Conclusao: Tres tarefas sobre extensoes, comprimento e intervalos para praticar globbing.

Lina: Entendi a teoria. Quero tentar na pratica.
Veterano Linny: Otimo, preparei tres tarefas. Crie os arquivos de pratica primeiro, depois tente resolve-las.
# Preparar arquivos de pratica
$ touch a.txt b.txt c.log data1.csv data2.csv data10.csv

Tarefa 1: Liste apenas os arquivos terminando em .csv.

Mostrar dica

Expresse "algo + .csv" com *.

Resposta exemplo
$ ls *.csv

Isso mostra data1.csv, data2.csv e data10.csv.

Tarefa 2: Liste apenas data + um caractere + .csv (excluindo data10.csv).

Mostrar dica

O simbolo para um caractere e ?.

Resposta exemplo
$ ls data?.csv

Apenas data1.csv e data2.csv permanecem. data10.csv e excluido porque tem dois caracteres.

Tarefa 3: Mostre apenas data1.csv e data2.csv usando colchetes.

Mostrar dica

Coloque 1 e 2 como candidatos dentro de [].

Resposta exemplo
$ ls data[12].csv

[12] significa "um caractere, 1 ou 2." data10.csv e excluido.

Proximas Leituras