Iterate through a directory but start from different file? - php

Is there a way to start from a different file eg. one that starts with "M" rather than with the very first file in a directory when iterating thru it (including sub-directories) with the following code?:
$filename = "/Users/jMac-NEW/Desktop";
$it = new RecursiveDirectoryIterator($filename, RecursiveDirectoryIterator::SKIP_DOTS);
foreach (new RecursiveIteratorIterator($it) as $file) { ...

Your RecursiveDirectoryIterator is a recursive iterator so you need to wrap that in a RecursiveIteratorIterator to traverse through subdirectories.
You can then filter that with a RegexIterator creating a pattern to filter out those files that you don't want to begin with.
$filename = __DIR__;
$it = new RegexIterator(
new RecursiveIteratorIterator(
new RecursiveDirectoryIterator($filename, RecursiveDirectoryIterator::SKIP_DOTS)
),
sprintf('|^%s[^A-La-l].*$|', preg_quote($filename . DIRECTORY_SEPARATOR, '|')
);
var_dump(iterator_to_array($it));

Related

How to loop and get data of all nested files and subfolders

I have a top folder named home and nested folders and files inside
I need to insert some data from files and folders into a table
The following (simplified) code works fine if I manually declare parent folder for each level separatelly, i.e. - home/lorem/, home/impsum/, home/ipsum/dolor/ etc
Is there a way to do this automatically for all nested files and folders ?
Actually, I need the path for each of them on each level
$folders = glob("home/*", GLOB_ONLYDIR);
foreach($folders as $el){
//$path = ??;
//do_something_with folder;
}
$files = glob("home/*.txt");
foreach($files as $el){
//$path = ??;
//do_something_with file;
}
PHP has the recursiveIterator suite of classes - of which the recursiveDirectoryIterator is the correct tool for the task at hand.
# Where to start the recursive scan
$dir=__DIR__;
# utility
function isDot( $dir ){
return basename( $dir )=='.' or basename( $dir )=='..';
}
# create new instances of both recursive Iterators
$dirItr=new RecursiveDirectoryIterator( $dir, RecursiveDirectoryIterator::KEY_AS_PATHNAME );
$recItr=new RecursiveIteratorIterator( $dirItr, RecursiveIteratorIterator::CHILD_FIRST );
foreach( $recItr as $obj => $info ) {
# directories
if( $info->isDir() && !isDot( $info->getPathname() ) ){
printf('> Folder=%s<br />',realpath( $info->getPathname() ) );
}
# files
if( $info->isFile() ){
printf('File=%s<br />',$info->getFileName() );
}
}
I would suggest you to use The Finder Component
use Symfony\Component\Finder\Finder;
$finder = new Finder();
// find all files in the home directory
$finder->files()->in('home/*');
// To output their path
foreach ($finder as $file) {
$path = $file->getRelativePathname();
}

How do I remove the dot using isDot() using RecursiveDirectoryIterator?

I have this simple below code to help me get the contents of all files and sub folder. I took this code from the PHP cook book. it says that I can use the isDot() but it doesn't explain how to ..
I tried to put a if just before array but it doesn't work...
if (! $file->isDot())
I don't know how to put both getPathname and isDot when adding to the array.
I've read the PHP net website but don't understand how to fit in.
code:
$dir = new RecursiveDirectoryIterator('/usr/local');
$dircontent = array();
foreach (new RecursiveIteratorIterator($dir) as $file) {
$dircontent [] = $file -> getPathname();
}
print_r($dircontent);
Use the FilesystemIterator::SKIP_DOTS flag in your RecursiveDirectoryIterator to get rid of dot files:
$dir = '/usr/local';
$result = array();
$files = new RecursiveIteratorIterator(
new RecursiveDirectoryIterator(
$dir,
FilesystemIterator::SKIP_DOTS
)
);
foreach ($files as $file) {
$result[] = $file->getPathname();
}
print_r($result);
The reason isDot() is failing is that your $file variable holds a SplFileInfo object, not a DirectoryIterator.

return all unique directories within a hierarchy

I'm using RecursiveDirectoryIterator to scan for all files and folders within a given root dir. This works fine, but I'd like to keep track of all of the unique directories in that list, so I'm not sure that RecursiveDirectoryIterator is the way to go.
I have a directory structure of
-a
->b
->c
-one
->two
->three
Here is my code:
<?php
function test($dir){
$in_dir = 'none';
$currdir = 'none';
$thisdir = new RecursiveDirectoryIterator($dir, RecursiveDirectoryIterator::SKIP_DOTS);
$files = new RecursiveIteratorIterator($thisdir, RecursiveIteratorIterator::SELF_FIRST);
foreach($files as $object){
//if this is a directory... find out which one it is.
if($object->isDir()){
//figure out if we have changed directories...
$currdir = realpath($object->getPath());
if(strpos($currdir, '.') == false){
$test = strcmp($currdir, $prevdir);
if($test){
echo "current dir changing: ", $currdir, "\n";
$prevdir = $currdir;
}
}
}
}
}
test('fold');
?>
What I get from that is the following:
current dir changing: /Users/<usr>/Desktop/test/fold
current dir changing: /Users/<usr>/Desktop/test/fold/a
current dir changing: /Users/<usr>/Desktop/test/fold/a/b
current dir changing: /Users/<usr>/Desktop/test/fold
current dir changing: /Users/<usr>/Desktop/test/fold/one
current dir changing: /Users/<usr>/Desktop/test/fold/one/two
...But I only want the unique directories.
It's perhaps the method of object comparison in the loop that returns duplicates, as the iterator moves up and down the directory tree as it parses through folders.
The following worked for me. I also use array_unique() confirm no dupes as a redundancy.
$dirArray = []; // the array to store dirs
$path = realpath('/some/folder/location');
$objects = new RecursiveIteratorIterator(
new RecursiveDirectoryIterator($path),
RecursiveIteratorIterator::SELF_FIRST
);
// loop through all objects and store names in dirArray[]
foreach($objects as $name => $object){
if ($object->isDir()) {
$dirArray[] = $name;
}
}
// make sure there are no dupes
$result = array_unique($dirArray);
// print array out
print_r($result);

Get list of subdirectories of specified PATH to specified number of child directories

I am using this code to get list of sub directories.
<?php
$path = '/www/sites/';
$directory_iterator = new RecursiveDirectoryIterator($path, RecursiveDirectoryIterator::KEY_AS_PATHNAME);
$iterator = new RecursiveIteratorIterator($directory_iterator,
RecursiveIteratorIterator::SELF_FIRST,
RecursiveIteratorIterator::CATCH_GET_CHILD);
foreach ($iterator as $file => $info) {
if ($info->isDir()) {
echo $file . "\n";
}
}
?>
But it is returning me something like this
/www/sites/000/4e7
/www/sites/000/4e7/.
/www/sites/000/4e7/..
/www/sites/000/4e7/mydomains.com
/www/sites/000/4e7/mydomains.com/.
/www/sites/000/4e7/mydomains.com/..
/www/sites/000/4e7/mydomains.com/web
/www/sites/000/4e7/mydomains.com/web/.
/www/sites/000/4e7/mydomains.com/web/..
/www/sites/000/4e7/mydomains.com/web/cgi-bin
/www/sites/000/4e7/mydomains.com/web/cgi-bin/.
/www/sites/000/4e7/mydomains.com/web/cgi-bin/..
/www/sites/000/4e7/mydomains.com/web/Resources
/www/sites/000/4e7/mydomains.com/web/Resources/.
I specified root path as /www/sites
What I only need in the above output is
/www/sites/000/4e7/mydomains.com
Rest are useless to me. It means I only want to crawl up to 3 sub directories from specified path. I have thousands of thousands of sub directories that's why I want to modify current code as it is taking too much time
Thank you in advance.
Use directoryiterator::isdot(), recursiveiteratoriterator::getdepth(), eg:
<?php
$path = '/www/sites/';
$directory_iterator = new RecursiveDirectoryIterator($path,RecursiveDirectoryIterator::KEY_AS_PATHNAME);
$iterator = new RecursiveIteratorIterator($directory_iterator,RecursiveIteratorIterator::SELF_FIRST,RecursiveIteratorIterator::CATCH_GET_CHILD);
foreach ($iterator as $file => $info) {
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// Restrict to 3 levels only and ignore non-directory and dot files
if ($info->getDepth() >= 3 || !$info->isDir() || $info->isDot())
continue;
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
echo $file . "\n";
}
Output
/www/sites/000
/www/sites/000/4e7
/www/sites/000/4e7/mydomains.com

How to ignore/exclude folders with RecursiveDirectoryIterator?

I'm using PharData to create a tar package. It works fine but it includes a folder i don't want. How can I exclude a folder in the archive?
<?php
$dir = "/foobar/dir";
$iterator = new RecursiveIteratorIterator(
new RecursiveDirectoryIterator($dir)
);
$phar = new PharData('/mytar.tar');
$phar->buildFromIterator($iterator, $dir);
$phar->compress(Phar::GZ);
unlink(realpath('/mytar.tar'));
The folder I want to ignore in the archive is vendor (/foobar/dir/vendor).
You can use CallbackFilterIterator() to filter the unwanted files and folders (not tested yet):
<?php
$dir = "/foobar/dir";
$iterator = new RecursiveIteratorIterator(
new RecursiveDirectoryIterator($dir)
);
$filterIterator = new CallbackFilterIterator($iterator , function ($file) {
return (strpos($file, "vendor/") === false);
});
$phar = new PharData('/mytar.tar');
$phar->buildFromIterator($filterIterator, $dir);
$phar->compress(Phar::GZ);
unlink(realpath('/mytar.tar'));

Categories