W3docs

fnmatch()

A função fnmatch() do PHP verifica se uma string corresponde a um padrão de curinga de shell, sendo usada para filtrar nomes de ficheiros.

O que é a Função fnmatch()?

A função fnmatch() verifica se uma string corresponde a um padrão de curinga de shell — o mesmo tipo de padrão que se escreve num terminal, como *.txt ou image-?.png. Ela retorna um boolean, por isso é usada com mais frequência para filtrar nomes de ficheiros ou outras strings sem precisar de escrever uma expressão regular completa.

Apesar do nome, fnmatch() nunca acede ao sistema de ficheiros. Ela apenas compara o padrão com a string fornecida, portanto funciona com qualquer texto, não apenas ficheiros reais.

Esta página aborda a assinatura da função, os caracteres curinga que ela reconhece, as flags opcionais e os casos práticos em que ela supera tanto glob() como as expressões regulares.

Sintaxe

fnmatch(string $pattern, string $filename, int $flags = 0): bool
  • $pattern — o padrão de curinga de shell a ser verificado.
  • $filename — a string a ser testada (não precisa de ser um ficheiro real).
  • $flags — flags de bit opcionais que alteram o comportamento da correspondência (ver Flags).

A função retorna true quando $filename corresponde a $pattern, e false caso contrário.

Exemplo Básico

php— editable, runs on the server

Aqui myfile.txt corresponde a *.txt, portanto o primeiro ramo é executado e imprime The string matches the pattern!. Substitua a string por myfile.csv e a correspondência falha.

Caracteres Curinga

fnmatch() reconhece os curingas padrão de shell. Saber exatamente o que cada um faz é fundamental para usar a função corretamente:

CuringaSignificadoPadrão de exemploCorrespondeNão corresponde
*Qualquer sequência de caracteres (incluindo nenhum)*.logerror.log, .logerror.txt
?Exatamente um caracterefile?.txtfile1.txtfile12.txt
[...]Um caractere do conjuntoimage.[jp]ngimage.jng, image.pngimage.gng
[!...]Um caractere não presente no conjunto[!0-9]*abc1abc

O exemplo a seguir percorre cada curinga para que os possa ver lado a lado:

<?php

var_dump(fnmatch("*.log", "error.log"));     // bool(true)  — * matches "error"
var_dump(fnmatch("file?.txt", "file1.txt")); // bool(true)  — ? matches one char
var_dump(fnmatch("file?.txt", "file12.txt"));// bool(false) — ? matches only ONE char
var_dump(fnmatch("img.[jp]ng", "img.png"));  // bool(true)  — p is in [jp]
var_dump(fnmatch("[!0-9]*", "abc"));          // bool(true)  — first char is not a digit
var_dump(fnmatch("[!0-9]*", "1abc"));         // bool(false) — first char IS a digit

Flags

O terceiro argumento aceita uma ou mais das seguintes constantes, combinadas com o operador OR bit a bit (|):

FlagEfeito
FNM_NOESCAPETrata uma barra invertida (\) literalmente em vez de como caractere de escape.
FNM_PATHNAMEUma barra (/) na string deve ser correspondida por um / literal — * e ? não a corresponderão.
FNM_PERIODUm ponto inicial na string deve ser correspondido explicitamente; * e ? não o corresponderão.
FNM_CASEFOLDCorrespondência sem distinção de maiúsculas e minúsculas.

FNM_CASEFOLD é a flag que será usada com mais frequência:

<?php

var_dump(fnmatch("*.PNG", "photo.png"));               // bool(false) — case differs
var_dump(fnmatch("*.PNG", "photo.png", FNM_CASEFOLD)); // bool(true)  — case ignored

Com FNM_PATHNAME, o curinga * para nos separadores de diretório, o que é útil ao fazer correspondência de caminhos completos:

<?php

var_dump(fnmatch("src/*.php", "src/index.php"));               // bool(true)
var_dump(fnmatch("src/*.php", "src/lib/db.php"));              // bool(true)  — * crosses the slash
var_dump(fnmatch("src/*.php", "src/lib/db.php", FNM_PATHNAME));// bool(false) — * cannot cross "/"

Um Caso de Uso Prático: Filtrar uma Lista de Ficheiros

Uma tarefa comum é manter apenas as entradas que correspondem a um padrão. Como fnmatch() funciona com strings simples, combina naturalmente com array_filter():

<?php

$files = ["report.pdf", "notes.txt", "draft.txt", "image.png"];

$textFiles = array_filter($files, fn($file) => fnmatch("*.txt", $file));

print_r(array_values($textFiles));

Isto imprime:

Array
(
    [0] => notes.txt
    [1] => draft.txt
)

fnmatch() vs. glob() vs. Expressões Regulares

Estas três ferramentas se sobrepõem, portanto escolher a certa é importante:

  • Use glob() quando quiser ler ficheiros reais do disco que correspondam a um padrão. Ela acede ao sistema de ficheiros e retorna os caminhos correspondentes.
  • Use fnmatch() quando já tiver strings (nomes de ficheiros, chaves, etiquetas) em memória e precisar apenas de uma verificação verdadeiro/falso em relação a um padrão de curinga.
  • Use preg_match() quando precisar de toda a potência das expressões regulares — grupos de captura, alternância, quantificadores — que curingas simples não conseguem expressar.

Armadilhas

  • Não é o sistema de ficheiros. fnmatch() não verifica se um ficheiro existe; apenas compara strings. Para acesso ao disco, use glob().
  • Disponibilidade. Em versões do Windows anteriores ao PHP 7.2, fnmatch() pode estar indisponível. Envolva as chamadas em function_exists('fnmatch') se precisar de suportar esses ambientes.
  • Os padrões não são regex. * significa "quaisquer caracteres", não "zero ou mais do token anterior". Se escrever a+ esperando um quantificador de regex, será tratado como os dois caracteres literais a e +.
  • Ficheiros ocultos. Por padrão, * corresponde a um ponto inicial, portanto * corresponde a .gitignore. Adicione FNM_PERIOD se quiser ignorar dotfiles como faz um shell.

Conclusão

fnmatch() é a forma mais simples de testar uma string em relação a um padrão de curinga no estilo de shell em PHP. Recorra a ela quando precisar de filtragem de nomes de ficheiros rápida e legível sem o custo de uma expressão regular — e lembre-se dos seus companheiros glob() para ler ficheiros do disco e preg_match() para qualquer coisa mais complexa que curingas.

Prática

Prática
Quais são os argumentos da função fnmatch() em PHP?
Quais são os argumentos da função fnmatch() em PHP?
Was this page helpful?