1

preg_match('/\.(?!pdf)$/', $file)

I want to match all files except pdf files

path/file.jpg # match
path/file.png # match
path/file.pdf # not match
splash58
  • 26,043
  • 3
  • 22
  • 34
clarkk
  • 27,151
  • 72
  • 200
  • 340

3 Answers3

1

Instead of using regex, you can take the extension of your file and check if it's a pdf.

$ext = pathinfo($file, PATHINFO_EXTENSION);
if($ext != 'pdf'){
    echo "I'm not a pdf";
}

If you prefer using regex

<?php
$file = array("path/file.jpg", "path/file.png", "path/file.pdf");
foreach ($file as &$value) {
    preg_match('/^(.(?!.*\.pdf$))*$/', $value, $matches);
    if(!empty($matches)){
        echo " $value is not a pdf";
    }
}

https://regex101.com/r/7C7YsR/1

executable
  • 3,365
  • 6
  • 24
  • 52
1

If you want to use a regex, this one will work:

^(?!.*\.pdf).*$

It simply uses a negative lookahead to assert that the filename doesn't end in .pdf and then .* to match everything in the filename.

Demo on regex101

In PHP:

$filenames = array('path/file.jpg','path/file.png','path/file.pdf');
foreach ($filenames as $filename) {
    if (preg_match('/^(?!.*\.pdf).*$/', $filename)) echo "\"$filename\" is not a PDF file.\n";
}

Output:

"path/file.jpg" is not a PDF file. 
"path/file.png" is not a PDF file.

Demo on 3v4l.org

Nick
  • 138,499
  • 22
  • 57
  • 95
0

Asserting that something is not present in a regex is often fiddly, because a regex works by looking through the input for things to match.

The approach you've used is a "zero-width negative look-ahead assertion" - it matches anywhere in the string that isn't followed by pdf, but doesn't "use up" any input. So your regex doesn't work because the rest of it still needs to match, and that is /\.$/, meaning ". at end of string".

The simplest approach is to look for strings that do end .pdf, e.g. if ( ! preg_match('/\.pdf$/', $file) ) { ... }.

IMSoP
  • 89,526
  • 13
  • 117
  • 169