Read all files in directory except - php

The function below returns an array of XML files from a given directory including all subdirectories. How can I modify this function by passing a second optional parameter which excludes a directory.
E.g:
getDirXmlFiles($config_dir, "example2");
Directory/Files
/file1.xml
/file2.xml
/examples/file3.xml
/examples/file4.xml
/example2/file5.xml
/example2/file5.xml
In the above case the function would return all files except files in the example2 directory.
function getDirXmlFiles($base) {
$files = array();
if(!is_dir($base)) return $files;
if ($handle = opendir($base)) {
while (false !== ($file = readdir($handle))) {
if ($file == "." || $file == "..") continue;
if(is_dir("$base/$file")) {
$subfiles = $this->getDirXmlFiles("$base/$file");
$files = array_merge($files, $subfiles);
} else {
if(Cms_File::type($file,false) == "xml")
$files[] = "$base/$file";
}
}
closedir($handle);
}
return $files;
}

Try this:
function getDirXmlFiles($base, $exclude = NULL) {
$files = array();
if(!is_dir($base)) return $files;
if ($handle = opendir($base)) {
while (false !== ($file = readdir($handle))) {
if ($file == "." || $file == ".." || "$base/$file" == $exclude) continue;
if(is_dir("$base/$file")) {
$subfiles = $this->getDirXmlFiles("$base/$file",$exclude);
$files = array_merge($files, $subfiles);
} else {
if(Cms_File::type($file,false) == "xml")
$files[] = "$base/$file";
}
}
closedir($handle);
}
return $files;
}

Redefine the function inputs:
function getDirXmlFiles($base, $excludeDir) {
Then change this line:
if(is_dir("$base/$file")) {
to this:
if(is_dir("$base/$file") && "$base/$file" != "$base/$excludeDir") {

You can just slightly modify the function to check and see if the current directory is the one you want to exclude or not
function getDirXmlFiles($base,$exclude) {
$files = array();
if(!is_dir($base)) return $files;
if ($handle = opendir($base)) {
while (false !== ($file = readdir($handle))) {
if ($file == "." || $file == "..") continue;
if(is_dir("$base/$file") && $file != $exclude) {
$subfiles = $this->getDirXmlFiles("$base/$file",$exclude);
$files = array_merge($files, $subfiles);
} else {
if(Cms_File::type($file,false) == "xml")
$files[] = "$base/$file";
}
}
closedir($handle);
}
return $files;
}

Smth of the sort ( tested only the syntax validation there might be needed some small debugging ) ( this will allow you to exclude multiple directory names )
function getDirXmlFiles($base, $excludeArray = array()) {
if (!is_array($excludeArray))
throw new Exception(__CLASS__ . "->" . __METHOD__ . " expects second argument to be a valid array");
$files = array();
if(!is_dir($base)) return $files;
if ($handle = opendir($base)) {
while (false !== ($file = readdir($handle))) {
$path = $base . "/" . $file;
$isDir = is_dir($path);
if (
$file == "."
|| $file == ".."
|| (
$isDir
&& count($excludeArray) > 0
&& in_array($file, $excludeArray)
)
)
continue;
if($isDir) {
$subfiles = $this->getDirXmlFiles($path, $excludeArray);
$files = array_merge($files, $subfiles);
} else {
if(Cms_File::type($file,false) == "xml")
$files[] = $path;
}
}
closedir($handle);
}
return $files;
}

Related

PHP Multi Directory delete

So I'm creating an image upload site and I need to delete multiple directories and files simultaneously. I have managed to create code that does the job however I'm unsure whether this is 'good code' as I'm repeating myself.
Is there a better way to write the below?
$dirname = 'uploads/'.$album_id;
$dirnamethumb = 'uploads/thumbs/'.$album_id;
if (is_dir($dirname))
$dir_handle = opendir($dirname);
if (!$dir_handle)
return false;
while($file = readdir($dir_handle)) {
if ($file != "." && $file != "..") {
if (!is_dir($dirname."/".$file))
unlink($dirname."/".$file);
else
delete_directory($dirname.'/'.$file);
}
}
if (is_dir($dirnamethumb))
$dir_handle = opendir($dirnamethumb);
if (!$dir_handle)
return false;
while($file = readdir($dir_handle)) {
if ($file != "." && $file != "..") {
if (!is_dir($dirnamethumb."/".$file))
unlink($dirnamethumb."/".$file);
else
delete_directory($dirnamethumb.'/'.$file);
}
}
closedir($dir_handle);
rmdir($dirname);
rmdir($dirnamethumb);
return true;
Thank you in advance for your help!
Why not try this recursive function from similar question
function rrmdir($dir) {
foreach(glob($dir . '/*') as $file) {
if(is_dir($file))
rrmdir($file);
else
unlink($file);
} rmdir($dir);
}
try this,
$dir = '/path/to/some/dir/'; // notice: trailing slash!
if ($handle = opendir($dir)) {
while (false !== ($entry = readdir($handle))) {
if (is_dir($dir . $entry) ) {
rmdir($dir . $entry);
}
}
closedir($handle);
}
?>

php function to read subdir content

I would like to ask what I have to add to make this function to show not only the files on top dir but also the files in subdirs..
private function _populateFileList()
{
$dir_handle = opendir($this->_files_dir);
if (! $dir_handle)
{
return false;
}
while (($file = readdir($dir_handle)) !== false)
{
if (in_array($file, $this->_hidden_files))
{
continue;
}
if (filetype($this->_files_dir . '/' . $file) == 'file')
{
$this->_file_list[] = $file;
}
}
closedir($dir_handle);
return true;
}
Thank you in advance!
You could implement the recursion yourself, or you could use the existing iterator classes to handle the recursion and filesystem traversal for you:
$dirIterator = new RecursiveDirectoryIterator('.', FilesystemIterator::SKIP_DOTS);
$recursiveIterator = new RecursiveIteratorIterator($dirIterator);
$filterIterator = new CallbackFilterIterator($recursiveIterator, function ($file) {
// adjust as needed
static $badFiles = ['foo', 'bar', 'baz'];
return !in_array($file, $badFiles);
});
$files = iterator_to_array($filterIterator);
var_dump($files);
By this you can get all subdir content
customerdel('FolderPath');
function customerdel($dirname=null){
if($dirname!=null){
if (is_dir($dirname))
$dir_handle = opendir($dirname);
if (!$dir_handle)
return false;
while($file = readdir($dir_handle)) {
if ($file != "." && $file != "..") {
if (!is_dir($dirname."/".$file))
echo $dirname."/".$file.'<br>';
else{
echo $dirname.'/'.$file.'<br> ';
customerdel($dirname.'/'.$file);
}
}
}
closedir($dir_handle);
}
}
Here is how you can get a recursive array of all files in a directory and its subdirectories.
The returned array is like: array( [fileName] => [filePath] )
EDIT: I've included a small check if there are filenames in the subdirectories with the same name. If so, an underscore and counter is added to the key-name in the returned array:
array( [fileName]_[COUNTER] => [filePath] )
private function getFileList($directory) {
$fileList = array();
$handle = opendir($directory);
if ($handle) {
while ($entry = readdir($handle)) {
if ($entry !== '.' and $entry !== '..') {
if (is_dir($directory . $entry)) {
$fileList = array_merge($fileList, $this->getFileList($directory . $entry . '/'));
} else {
$i = 0;
$_entry = $entry;
// Check if filename is allready in use
while (array_key_exists($_entry, $fileList)) {
$i++;
$_entry = $entry . "_$i";
}
$fileList[$_entry] = $directory . $entry;
}
}
}
closedir($handle);
}
return $fileList;
}

Opendir get array of files before files in sub folder

I have a function which returns an array of files in a folder recursive.
protected function getFiles($base) {
$files = array();
if(!is_dir($base)) return $files;
if (($handle = opendir($base)) != false) {
while (false !== ($file = readdir($handle))) {
if ($file == "." || $file == "..") continue;
if(is_dir("$base/$file")) {
$subfiles = $this->getFiles("$base/$file");
$files = array_merge($files, $subfiles);
} else {
if(File::type($file,false) == "xml")
$files[] = "$base/$file";
}
}
closedir($handle);
}
return $files;
}
How can I modify this so that it always lists the root files first before any sub folders? At the moment by default the folders always come first.
You may want to take a look at the PHP SPL DirectoryIterator Class. You can instantiate the object and then quickly iterate over to segment out directories vs. files vs. links and get the full SplFileInfo object for each (which makes it really easy to get whatever info you want about the files).
$directory = '/path/to/directory';
$iterator = new DirectoryIterator($directory);
$dirs = array();
$files = array();
$links = array();
foreach($iterator as $obj) {
if($obj->isFile()) {
$files[] = $obj;
} else if ($obj->isDir()) {
$dirs[] = $obj;
} else if ($obj->isLink()) {
$links[] = $obj;
}
}
Sorry just realized you wanted to do it recursively. Well for that use RecursiveDirectoryIterator , but concept is much the same.
Just create an array of sub-directories while you loop the directory pointer, and iterate the array of directories at the end:
protected function getFiles($base) {
$files = $dirs = array();
if(!is_dir($base)) return $files;
if (($handle = opendir($base)) != false) {
while (false !== ($file = readdir($handle))) {
if ($file == "." || $file == "..") continue;
if(is_dir("$base/$file")) {
$dirs[] = "$base/$file";
} else {
if(File::type($file,false) == "xml")
$files[] = "$base/$file";
}
}
closedir($handle);
foreach ($dirs as $dir) {
$subfiles = $this->getFiles($dir);
$files = array_merge($files, $subfiles);
}
}
return $files;
}
Use two arrays one for the files in the current folder and one for the those in subfolders then merge them.
protected function getFiles($base) {
$files = array();
$subFiles = array();
if(!is_dir($base)) return $files;
if (($handle = opendir($base)) != false) {
while (false !== ($file = readdir($handle))) {
if ($file == "." || $file == "..") continue;
if(is_dir("$base/$file")) {
$subFiles = array_merge($subFiles, $this->getFiles("$base/$file"));
} else {
if(File::type($file,false) == "xml")
$files[] = "$base/$file";
}
}
closedir($handle);
}
return array_merge($files, $subFiles);
}

How to scan all the .m files using php? [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
php scandir --> search for files/directories
I have a folder, inside this folder, have many subfolders, but I would like to scan all the subfolders, and scan all the .m file... How can I do so??
Here is the file:
/MyFilePath/
/myPath.m
/myPath2.m
/myPath3.m
/MyClasses/
/my.m
/my1.m
/my2.m
/my3.m
/Utilities/
/u1.m
/u2.m
/External/
/a.m
/b.m
/c.m
/Internal/
/d.m
/e.m
/f.m
/Views/
/a_v.m
/b_v.m
/c_v.m
/Controllers/
/a_vc.m
/b_vc.m
/c_vc.m
/AnotherClasses/
/anmy.m
/anmy1.m
/anmy2.m
/anmy3.m
/Networking/
/net1.m
/net2.m
/net3.m
/External/
/Internal/
/Views/
/Controllers/
You could also use some of the SPL's iterators. A quick and basic example would look like:
$directories = new RecursiveDirectoryIterator('path/to/search');
$flattened = new RecursiveIteratorIterator($directories);
$filter = new RegexIterator($flattened, '/\.in$/');
foreach ($filter as $file) {
echo $file, PHP_EOL;
}
More infos (mostly incomplete):
http://php.net/recursivedirectoryiterator
http://php.net/recursiveiteratoriterator
http://php.net/regexiterator
You can use a recursive function like this:
function searchFiles($dir,$pattern,$recursive=false)
{
$matches = array();
$d = dir($dir);
while (false !== ($entry = $d->read()))
{
if (is_dir($d->path.$entry) && $recursive)
{
$subdir = $d->path.$entry;
$matches = array_merge($matches,searchFiles($dir,$pattern,$recursive));
}
elseif (is_file($d->path.$entry) && preg_match($pattern,$entry))
{
$matches[] = $d->path.$entry;
}
}
$d->close();
return $matches;
}
Usage:
$matches = searchFiles("/mypath/","'[.]m$'i",true);
function ScanForMFiles($dir){
$return = array();
if ($handle = opendir($dir)) {
while (false !== ($file = readdir($handle))) {
if ($file != "." && $file != "..") {
if(is_dir($dir.$file)){
$return = array_merge($return, ScanForMFiles($dir.$file."/"));
}
else {
if(substr($file, -2) == '.m')
$return[] = $file;
}
}
}
closedir($handle);
}
return $return;
}
var_dump(ScanForMFiles('./'));
You'll want to look to the PHP docs for details on this: http://php.net/manual/en/function.readdir.php
Here's an example that should do what you you want. It will return an array of all .m files in the sub directories. You can then loop through each file and read the contents if that is what you are interested in.
<?php
function get_m_files($root = '.'){
$files = array();
$directories = array();
$last_letter = $root[strlen($root)-1];
$root = ($last_letter == '\\' || $last_letter == '/') ? $root : $root.DIRECTORY_SEPARATOR;
$directories[] = $root;
while (sizeof($directories)) {
$dir = array_pop($directories);
if ($handle = opendir($dir)) {
while (false !== ($file = readdir($handle))) {
if ($file == '.' || $file == '..') {
continue;
}
$file = $dir.$file;
if (is_dir($file)) {
$directory_path = $file.DIRECTORY_SEPARATOR;
array_push($directories, $directory_path);
} elseif (is_file($file)) {
if (substr( $file, -strlen( ".m" ) ) == ".m") {
$files[] = $file;
}
}
}
closedir($handle);
}
}
return $files;
}
?>

How to delete all files under a specified directory with PHP?

I think the title is clear.
$dir = '/some/path/to/delete/';//note the trailing slashes
$dh = opendir($dir);
while($file = readdir($dh))
{
if(!is_dir($file))
{
#unlink($dir.$file);
}
}
closedir($dh);
function Delete($path)
{
if (is_dir($path) === true)
{
$files = array_diff(scandir($path), array('.', '..'));
foreach ($files as $file)
{
Delete(realpath($path) . '/' . $file);
}
return rmdir($path);
}
else if (is_file($path) === true)
{
return unlink($path);
}
return false;
}
http://us.php.net/manual/en/function.unlink.php.
You will find many functions in the comments that does what you need
One example:
function unlinkRecursive($dir, $deleteRootToo)
{
if(!$dh = #opendir($dir))
{
return;
}
while (false !== ($obj = readdir($dh)))
{
if($obj == '.' || $obj == '..')
{
continue;
}
if (!#unlink($dir . '/' . $obj))
{
unlinkRecursive($dir.'/'.$obj, true);
}
}
closedir($dh);
if ($deleteRootToo)
{
#rmdir($dir);
}
return;
}
This function will remove recursively (like rm -r). Be careful!
function rm_recursive($filepath)
{
if (is_dir($filepath) && !is_link($filepath))
{
if ($dh = opendir($filepath))
{
while (($sf = readdir($dh)) !== false)
{
if ($sf == '.' || $sf == '..')
{
continue;
}
if (!rm_recursive($filepath.'/'.$sf))
{
throw new Exception($filepath.'/'.$sf.' could not be deleted.');
}
}
closedir($dh);
}
return rmdir($filepath);
}
return unlink($filepath);
}

Categories