O módulo glob é conhecido por localizar arquivos usando padrões como *.py, dados/**/*.csv e relatorio-??.pdf. Em versões recentes do Python, a função glob.translate() permite transformar um padrão glob em uma expressão regular. Isso é útil quando você quer reaproveitar a sintaxe simples dos globs, mas precisa aplicar a correspondência em textos, caminhos virtuais, listas vindas de uma API ou estruturas que não estão diretamente no sistema de arquivos.
Neste guia, você vai entender como glob.translate funciona, quais diferenças existem em relação a fnmatch.translate, como lidar com diretórios recursivos, separadores de caminho, arquivos ocultos e validação segura de padrões.
O que é glob.translate
glob.translate(pattern) recebe um padrão glob e devolve uma string de expressão regular compatível com o módulo re. O resultado pode ser compilado com re.compile() e usado várias vezes. Isso evita reimplementar manualmente regras de *, ?, classes de caracteres e caminhos recursivos.
import glob
import re
regex = re.compile(glob.translate("src/**/*.py", recursive=True))
caminhos = [
"src/app.py",
"src/api/routes.py",
"tests/test_app.py",
]
selecionados = [c for c in caminhos if regex.match(c)]
print(selecionados)
O padrão é interpretado como caminho, não como texto genérico. Por isso, o separador de diretórios tem importância e o caractere * normalmente não atravessa separadores.
Diferença entre glob e regex
Globs foram criados para serem simples. O asterisco representa uma sequência de caracteres, a interrogação representa um caractere e colchetes representam classes. Expressões regulares são muito mais poderosas, mas também mais difíceis de ler e mais propensas a erros. glob.translate cria uma ponte entre as duas abordagens.
Use glob quando usuários ou arquivos de configuração precisam fornecer filtros legíveis. Converta para regex quando você precisa aplicar o filtro repetidamente, combinar com outras validações ou usar dados que não estão em disco.
Correspondência recursiva com dois asteriscos
Quando recursive=True, o padrão ** pode representar vários níveis de diretório. Isso permite selecionar arquivos em árvores profundas.
pattern = "projeto/**/test_*.py"
regex = re.compile(glob.translate(pattern, recursive=True))
for caminho in caminhos:
if regex.match(caminho):
print(caminho)
Sem recursive=True, o comportamento de ** não deve ser tratado como travessia arbitrária de diretórios. Ao aceitar padrões de usuários, defina explicitamente essa opção para evitar resultados inesperados.
Arquivos e diretórios ocultos
Em sistemas Unix, nomes iniciados por ponto são tratados como ocultos. A opção include_hidden controla se curingas podem corresponder a esses componentes. Essa distinção é importante em ferramentas de backup, indexadores e analisadores de projetos, porque pastas como .git, .venv e .cache podem aumentar muito o volume processado.
regex = re.compile(
glob.translate("**/*.toml", recursive=True, include_hidden=False)
)
Mesmo quando você trabalha apenas com listas de strings, essa regra continua útil para reproduzir o comportamento esperado do módulo glob.
Separadores personalizados
A função pode aceitar separadores específicos. Isso é interessante quando os caminhos vêm de um arquivo ZIP, de uma API, de um banco de dados ou de um sistema remoto. Em arquivos ZIP, por exemplo, a barra normal costuma ser usada mesmo no Windows.
regex = re.compile(
glob.translate("assets/**/*.png", recursive=True, seps="/")
)
Ao fixar o separador, você torna o filtro previsível entre plataformas. Essa prática também facilita testes automatizados.
glob.translate versus fnmatch.translate
fnmatch.translate converte padrões voltados a nomes, enquanto glob.translate entende segmentos de caminho. Em um glob de caminhos, o separador possui significado especial. Já o fnmatch costuma tratar o texto como uma sequência única.
Se o seu filtro é apenas para nomes como foto-*.jpg, fnmatch pode ser suficiente. Para padrões com diretórios, recursão e controle de arquivos ocultos, glob.translate é mais apropriado.
Compile a regex uma única vez
Quando o mesmo padrão será aplicado a milhares de itens, compile a expressão regular uma vez. Isso reduz trabalho repetido e deixa o código mais claro.
def criar_filtro(pattern, *, recursive=False):
expressao = glob.translate(pattern, recursive=recursive)
return re.compile(expressao)
filtro = criar_filtro("logs/**/*.json", recursive=True)
resultados = [p for p in caminhos if filtro.match(p)]
Se os padrões mudam dinamicamente, você pode manter um cache pequeno. Porém, limite a quantidade de padrões aceitos para evitar consumo de memória desnecessário.
Validação e segurança
Padrões glob não executam código, mas ainda podem causar problemas de desempenho. Um padrão muito amplo pode selecionar milhões de caminhos. Em aplicações web, não use diretamente um padrão recebido do usuário para percorrer todo o servidor. Restrinja a raiz, limite profundidade, tamanho do padrão e quantidade de resultados.
Ao trabalhar apenas com strings, o risco de acesso ao sistema de arquivos diminui, mas ainda existe a possibilidade de processamento excessivo. Defina limites e rejeite padrões anormalmente longos.
Exemplo com caminhos vindos de uma API
Imagine uma API que retorna chaves de objetos armazenados em nuvem. Você quer filtrar apenas imagens dentro da pasta de um projeto.
objetos = [
"clientes/acme/logo.png",
"clientes/acme/docs/manual.pdf",
"clientes/acme/screens/home.webp",
"clientes/outro/logo.png",
]
padrao = "clientes/acme/**/*.[pw][ne][gb]"
regex = re.compile(glob.translate(padrao, recursive=True, seps="/"))
filtrados = [item for item in objetos if regex.match(item)]
Para extensões variadas, muitas vezes é mais legível combinar vários filtros ou verificar o sufixo com pathlib. Não force um único padrão a resolver toda a lógica.
Integração com pathlib
pathlib oferece uma API orientada a objetos para caminhos. Você pode normalizar dados com PurePosixPath antes de aplicar o regex.
from pathlib import PurePosixPath
normalizados = [PurePosixPath(p).as_posix() for p in objetos]
filtrados = [p for p in normalizados if regex.match(p)]
Essa combinação é útil em aplicações multiplataforma. Veja também nosso conteúdo sobre pathlib no Python, o guia de expressões regulares, o artigo sobre módulo os e o tutorial de arquivos grandes.
Testes recomendados
Crie testes para caminhos na raiz, caminhos profundos, nomes ocultos, separadores diferentes e strings que quase correspondem. Também teste padrões vazios, extensões em maiúsculas e caminhos com espaços.
casos = {
"src/main.py": True,
"src/api/main.py": True,
"src/.cache/main.py": False,
"tests/main.py": False,
}
filtro = re.compile(glob.translate("src/**/*.py", recursive=True))
for caminho, esperado in casos.items():
assert bool(filtro.match(caminho)) is esperado
Quando usar
Use glob.translate quando você precisa oferecer uma sintaxe de filtro simples e aplicar o resultado fora do sistema de arquivos. Ele funciona bem em indexadores, backups, ferramentas de build, listas de objetos em nuvem, manifestos e arquivos compactados.
Para consultar detalhes oficiais, veja a documentação do módulo glob e a documentação do módulo re. A principal recomendação é manter os padrões pequenos, previsíveis e acompanhados por testes.
Conclusão
glob.translate permite combinar a legibilidade dos padrões glob com a flexibilidade das expressões regulares. Ao entender recursão, separadores, arquivos ocultos e compilação, você consegue criar filtros portáveis e eficientes. Em projetos reais, valide padrões recebidos, limite o escopo e teste casos de borda para evitar correspondências inesperadas.







