php glob - scan in subfolders for a file
There are 2 ways.
Use glob
to do recursive search:
<?php
// Does not support flag GLOB_BRACE
function rglob($pattern, $flags = 0) {
$files = glob($pattern, $flags);
foreach (glob(dirname($pattern).'/*', GLOB_ONLYDIR|GLOB_NOSORT) as $dir) {
$files = array_merge(
[],
...[$files, rglob($dir . "/" . basename($pattern), $flags)]
);
return $files;
}
// usage: to find the test.zip file recursively
$result = rglob($_SERVER['DOCUMENT_ROOT'] . '/test.zip');
var_dump($result);
// to find the all files that names ends with test.zip
$result = rglob($_SERVER['DOCUMENT_ROOT'] . '/*test.zip');
?>
Use RecursiveDirectoryIterator
<?php
// $regPattern should be using regular expression
function rsearch($folder, $regPattern) {
$dir = new RecursiveDirectoryIterator($folder);
$ite = new RecursiveIteratorIterator($dir);
$files = new RegexIterator($ite, $regPattern, RegexIterator::GET_MATCH);
$fileList = array();
foreach($files as $file) {
$fileList = array_merge($fileList, $file);
}
return $fileList;
}
// usage: to find the test.zip file recursively
$result = rsearch($_SERVER['DOCUMENT_ROOT'], '/.*\/test\.zip/'));
var_dump($result);
?>
RecursiveDirectoryIterator
comes with PHP5 while glob
is from PHP4. Both can do the job, it's up to you.
How to check if a folder has sub folders using glob?
OK albeit not the way I wanted to, but after glob for some reason refuses to behave as expected I I instead opted to just scan the directory again and sorted it so that folders are first in the array. Then I just checked if the first element is a directory.
if(is_dir($link))
{
$folders = scandir($link, 1);
if(is_dir($link.'/'.$folders[0]))
{
echo $link." ";
echo "Has Sub-folders ";
}
Foreach glob to include files in a subdirectory
Use this for testing:
foreach (glob("addons/*.php", GLOB_NOCHECK) as $filename) {
PRINT $filename . "\n";
}
Should the directory not exist relatively to the current, then it will show addons/*.php
as output.
search for files with established criteria php
The following syntax can be used:
^.*(FRGHSD02D5102T|005878).+$
This would match any line that contains FRGHSD02D5102T
or 005878
:
00256_FRGHSD02D5102T0013005878.TXT ✅
FRGHSD02D5102T00256_0013005878.TXT ✅
_FRGHSD02D5102T001300587800256.TXT ✅
00256_005878.TXT ✅
FRGHSD02D5102T.TXT ✅
00058_GHT52DSF56S03U0014002545.TXT ❌
00256_005873.TXT ❌
This can be combined with glob to search through all folders and subfolders for the specific pattern:
$folder = __DIR__ . '/data';
$pattern = '/^.*(FRGHSD02D5102T|005878).+$/';
$dir = new RecursiveDirectoryIterator($folder);
$ite = new RecursiveIteratorIterator($dir);
$files = new RegexIterator($ite, $pattern, RegexIterator::GET_MATCH);
foreach($files as $file) {
echo 'found matching file: ' . $file[0] . PHP_EOL;
}
the folder structure:
data
|-- 00256_FRGHSD02D5102T0013005878.TXT
|-- example.TXT
`-- test
`-- YES256_FRGHSD02D5102T0013005878.TXT
the result:
found matching file: /Users/stackoverflow/dev/data/00256_FRGHSD02D5102T0013005878.TXT
found matching file: /Users/stackoverflow/dev/data/test/YES256_FRGHSD02D5102T0013005878.TXT
When searching for an specific extension the following snippet can be used:
$pattern = '/^.*(FRGHSD02D5102T|005878|001|002).*\.pdf$/';
.txt
$pattern = '/^.*(FRGHSD02D5102T|005878|001|002).*\.TXT$/';
.pdf, .PDF, .PdFm, contains 001 and 002 OR 002 and 001
$pattern = '/^.*(FRGHSD02D5102T|005878|001.*002|002.*001).*\.pdf/i';
matches:
data
|-- 00256_FRGHSD02D5102T0013005878.TXT ❌
|-- example.TXT ❌
|-- hell001hello.pdf ❌
|-- hell001hello002.pdf ✅
|-- hell002hello001.pdf ✅
`-- test
`-- YES256_FRGHSD02D5102T0013005878.TXT ❌
The /i
makes it case-insensitive so it will match any casing of PDF
.
The \.
escapes the .
because we need to match the literal .
instead of matching all characters.
Scan directory for files with specific extensions recursively
It looks like the PHP glob()
function does what you want:
The glob() function searches for all the pathnames matching pattern
according to the rules used by the libc glob() function, which is
similar to the rules used by common shells.
foreach (glob("*.txt") as $filename) {
echo "$filename size " . filesize($filename) . "\n";
}
And here is a nifty function by agd243 that uses glob() to find all files by extension an return it as an array:
function findFiles($directory, $extensions = array()) {
function glob_recursive($directory, &$directories = array()) {
foreach(glob($directory, GLOB_ONLYDIR | GLOB_NOSORT) as $folder) {
$directories[] = $folder;
glob_recursive("{$folder}/*", $directories);
}
}
glob_recursive($directory, $directories);
$files = array ();
foreach($directories as $directory) {
foreach($extensions as $extension) {
foreach(glob("{$directory}/*.{$extension}") as $file) {
$files[$extension][] = $file;
}
}
}
return $files;
}
var_dump(findFiles("C:\\baseFolder", array (
"src",
"in",
"out",
"rc"
)));
How to create subdirectory arrays with glob
You have a fixed low depth, so you don't really need recursive imho.
You can use wildcard * to mark different levels and GLOB_ONLYDIR to retrieve folders only :
$level1 = glob('MainFolder/*', GLOB_ONLYDIR);
$level2 = glob('MainFolder/*/*', GLOB_ONLYDIR);
$level3 = glob('MainFolder/*/*/*', GLOB_ONLYDIR);
If you want to store the last folder instead of full path you can use array_map() and basename() :
$level1 = array_map('basename', glob('MainFolder/*', GLOB_ONLYDIR));
...
PHP - reading folder, all subfolders, and files in subfolders
I think your issue comes from here :
while (false !== ($file = readdir($handle))) // it reads again the same directory as it did in the first while loop
Try to replace it with
if ($sub_handle = opendir($dir . $folder)) {
while (false !== ($file = readdir($sub_handle))) {
...
}
closedir($sub_handle);
}
Also, in your case, I would use php glob()
function
See a working example for your case :
$dir = './inspections/';
if ($handle = opendir($dir)) {
$blacklist = array('.', '..', 'default', 'default.php', 'desc.txt');
while (false !== ($folder = readdir($handle))) {
if (!in_array($folder, $blacklist)) {
foreach (glob($dir . $folder . "/*.png") as $filename) {
echo "$filename was found !";
echo "\r\n";
}
}
}
closedir($handle);
}
Output :
./inspections/location_4/img_1.png was found !
./inspections/location_4/img_2.png was found !
./inspections/location_4/img_3.png was found !
./inspections/location_4/img_4.png was found !
./inspections/location_4/img_5.png was found !
./inspections/location_4/img_6.png was found !
./inspections/location_3/img_1.png was found !
./inspections/location_3/img_2.png was found !
./inspections/location_3/img_3.png was found !
./inspections/location_3/img_4.png was found !
./inspections/location_3/img_5.png was found !
./inspections/location_3/img_6.png was found !
./inspections/location_2/img_1.png was found !
./inspections/location_2/img_2.png was found !
./inspections/location_2/img_3.png was found !
./inspections/location_2/img_4.png was found !
./inspections/location_2/img_5.png was found !
./inspections/location_2/img_6.png was found !
./inspections/location_1/img_1.png was found !
./inspections/location_1/img_2.png was found !
./inspections/location_1/img_3.png was found !
./inspections/location_1/img_4.png was found !
./inspections/location_1/img_5.png was found !
./inspections/location_1/img_6.png was found !
EDIT
To loop in the /inspections/location1/thumbs/ directories, this would work :
foreach (glob($dir . $folder . "/thumbs/*.png") as $filename) {
echo "$filename was found !";
echo "\r\n";
}
RE-EDIT
To glob multiple folders with the glob()
function, your code should look like :
foreach (glob($dir.$folder."{/thumbs/*.png,/*.png}", GLOB_BRACE) as $filename) {
echo "$filename was found !";
echo "\r\n";
}
Related Topics
How to Change Maximum Number of Post Variable in PHP
What Is a Front Controller and How Is It Implemented
How to Get JavaScript Function Data into a PHP Variable
PHP Pdo Prepared Statement - MySQL Like Query
Converting MySQL Result Array to Json
Best Way to Completely Destroy a Session - Even If the Browser Is Not Closed
Running Command-Line Application from PHP as Specific User
Merging Arrays With the Same Keys
Preserve Key Order (Stable Sort) When Sorting With PHP'S Uasort
Fatal Error: Cannot Use Object of Type MySQLi_Result
A Formula to Find Prime Numbers in a Loop
Import CSV File Directly into MySQL
Codeigniter: "The Filetype You Are Attempting to Upload Is Not Allowed."
PHP Is Confused When Adding and Concatenating