listing all jpg files in dir and subdirs - php

How can I list all jpg files in a given directory and its subdirectories in PHP5 ?
I thought I could write a glob pattern for that but I can't figure it out.
thanx, b.

You can use a RecursiveDirectoryIterator with a filter:
class ImagesFilter extends FilterIterator
{
public function accept()
{
$file = $this->getInnerIterator()->current();
return preg_match('/\.jpe?g$/i', $file->getFilename());
}
}
$it = new RecursiveDirectoryIterator('/var/images');
$it = new ImagesFilter($it);
foreach ($it as $file)
{
// Use $file here...
}
$file is an SplFileInfo object.

without doing it for you. recursion is the answer here. a function that looks in a dir and gets a list of all files. filters out only th jpg's then calls its self if i finds any sub dirs

Wish I had time to do more & test, but this could be used as a starting point: it should (untested) return an array containing all the jpg/jpeg files in the specified directory.
function load_jpgs($dir){
$return = array();
if(is_dir($dir)){
if($handle = opendir($dir)){
while(readdir($handle)){
echo $file.'<hr>';
if(preg_match('/\.jpg$/',$file) || preg_match('/\.jpeg$/',$file)){
$return[] = $file;
}
}
closedir($handle);
return $return;
}
}
return false;
}

Related

PHP Empty folder not deleting with rmdir command

My code is as below:
<?php
header("Location: ../");
unlink("index.php");
unlink("style.css");
unlink("success.php");
unlink("fail.php");
unlink("remove.php");
unlink("README.md");
unlink(".gitignore");
unlink(".git");
rmdir("../Humble-Installer");
die();
But every time I run it I receive the following error:
[17-Nov-2014 19:47:37 Pacific/Auckland] PHP Warning: unlink(.git): Operation not permitted in /Users/user/Humble/admin/Humble-Installer/remove.php on line 10
[17-Nov-2014 19:47:37 Pacific/Auckland] PHP Warning: rmdir(../Humble-Installer): Directory not empty in /Users/user/Humble/admin/Humble-Installer/remove.php on line 11
I have no idea, the directory is empty but will not delete... even if I remove the unlink(."git"); it still throws an error?
Cheers.
You can use this simple function to delete folder recursively:
function rrmdir($dir) {
if (is_dir($dir)) {
$objects = scandir($dir);
foreach ($objects as $object) {
if ($object != "." && $object != "..") {
if (filetype($dir."/".$object) == "dir") rrmdir($dir."/".$object); else unlink($dir."/".$object);
}
}
reset($objects);
rmdir($dir);
}
}
Notes:
unlink is for a file, .git is a directory, so it won't remove, use rmdir. If you want to do it recursively, use function I wrote above.
Update
If you want to use RecursiveIteratorIterator, you can use this function:
/**
* Remove directory recursively.
*
* #param string $dirPath Directory you want to remove.
*/
function recursive_rmdir($dirPath)
{
foreach (new RecursiveIteratorIterator(new RecursiveDirectoryIterator($dirPath, FilesystemIterator::SKIP_DOTS), RecursiveIteratorIterator::CHILD_FIRST) as $path) {
$pathName = $path->getPathname();
echo $pathName."\n";
($path->isDir() and ($path->isLink() === false)) ? rmdir($pathName) : unlink($pathName);
}
}
simplest function using glob
function removeDirectory($directory)
{
$files=glob($directory.'/*');
foreach ($files as $file)
{
if(is_dir($file))
{
removeDirectory($file);
continue;
}
unlink($file);
}
rmdir($directory);
}
this function will delete all the files and folders inside the given directory and at the end directory it self.

PHP dynamic multidimensional array creation

I'm scanning a folder and it's subfolders for files with PHP. I want to store the folders and files in a PHP array so I can create a treeview in another page. This is the format I get files paths in:
/home/project/index.php
/home/project/folder/myclass.php
/home/project/folder/myclass2.php
/home/project/folder/subfolder/anotherclass.php
I want to get these files in the following array:
[home][project] = array('index.php')
[home][project][folder] = array(myclass.php, myclass2.php)
[home][project][folder][subfolder] = array(anotherclass.php)
Note that the folder structure can change at any point. How can I achieve this?
The easiest way would be to use the built in (SPL) DirectoryIterator class and a simple recursive function.
An untested example:
public function directoryToArray($directoryPath)
{
$items = new DirectoryIterator($directoryPath);
$data = array();
foreach($items as $item) {
$name = $item->getFileName();
if ($item->isFile()) {
$data[] = $name;
}
else if ($item->isDir()) {
$data[$name] = directoryToArray($item->getPath());
}
}
return $data;
}

OOP problems with instance variables

I've got some problems with a piece of code in my two classes 'File' and 'Folder'. I've created a page which shows me the content of my server space. Therefore I've wrote the class Folder which contains information about it self like 'name', 'path' and 'children'. The children property contains an Array of 'Files' or 'Folders' within this folder. So it's a kind of recursive class. To get the whole structure of a wanted directory I've wrote some recursive backtracking algorithms that are giving me an array of objects for all children in the same structure as my folder on the server. The second algorithm is taking that array and searches an special folder. If it finds this folder the method will return the root path to it and if the folder isn't a subfolder of this directory the algorithm will return false. I've tested all of that methods for the 'Folder' object and it works just fine but now I've detected an error by using my script more intensive.
/**
* find an subfolder within the given directory (Recursive)
*/
public function findFolder($name) {
// is this object the object you wanted
if ($this->name == $name) {
return $this->getPath();
}
// getting array
$this->bindChildren();
$result = $this->getChildren();
// backtracking part
foreach($result as $r) {
// skip all 'Files'
if(get_class($r) == 'File') {
continue;
} else {
if($search_res = $r->findFolder($name)) {
return $search_res;
}
}
}
// loop runned out
return false;
}
/**
* stores all children of this folder
*/
public function bindChildren() {
$this->resetContent();
$this->dirSearch();
}
/**
* resets children array
*/
private function resetContent() {
$this->children = array();
}
/**
* storing children of this folder
*/
private function dirSearch() {
$dh = opendir($this->path);
while($file = readdir($dh)) {
if($file !== "" && $file !== "." && $file !== "..") {
if(!is_dir($this->path.$file)) {
$this->children[] = new File($this->path.$file);
} else {
$this->children[] = new Folder($this->path.$file.'/');
}
}
}
}
In my website I first create a new folder object and then I'm starting to find a subfolder of 'doc' which is call 'test' for example. The folder 'test' is in '/var/www/media/username/doc/test4/test/' located
$folder = new Folder('/var/www/media/username/doc/');
$dir = $folder->findFolder('test');
If I print out $dir it returns a link as I wanted because the folder 'test' is a subfolder of 'docs' but the returned link is not correct. it should be '/var/www/media/username/doc/test4/test' but the result is '/var/www/media/username/doc/test' I've tried to debugg a bit and found out that the folders list which contains all children is keeping the objects with the right links but in the findFolder method in the first if condition the object $this doesn't have the correct path. I don't know why but the the
// backtracking part
foreach($result as $r) {
seems to change the object properties. I hope someone can help me and thanks in advance
Don't reinvent the wheel. PHP already has a class for that purpose named RecursiveDirectoryIterator.
http://php.net/manual/en/class.recursivedirectoryiterator.php

find recursive specific file

I'm trying to find all the files that called "testunit.php".
In addition i want to cut the first 23 chars of the string.
I tried this but this is not working.I get all the files.
$it = new RecursiveDirectoryIterator($parent);
$display = Array ( 'testunit.php');
foreach (new RecursiveIteratorIterator($it) as $file=>$cur) {
{
if ( In_Array ( $cur, $display ) == true )
$file = substr($cur, 23)
fwrite($fh,"<file>$file</file>");
}
Thank you!
see if glob helps you
Try
class TestUnitIterator extends FilterIterator
{
public function accept()
{
return (FALSE !== strpos(
$this->getInnerIterator()->current(),
'testunit.php'
));
}
public function current()
{
return sprintf(
'<file>%s</file>',
substr($this->getInnerIterator()->current(), 23)
);
}
}
Usage (codepad (abridged example)):
$iterator = new TestUnitIterator(
new RecursiveIteratorIterator(
new RecursiveDirectoryIterator(
'/path/to/iterate/over',
FilesystemIterator::CURRENT_AS_PATHNAME
)
)
);
foreach ($iterator as $file) {
echo $file, PHP_EOL;
}
Disclaimer: I wasn't in the mood to mock the filesystem or setup the required test files, so the above might need a little tweaking to work with the filesystem. I only tested with an ArrayIterator but there shouldn't be much to do if the above produces errors.

Return total number of files within a folder using PHP

Is there a better/simpler way to find the number of images in a directory and output them to a variable?
function dirCount($dir) {
$x = 0;
while (($file = readdir($dir)) !== false) {
if (isImage($file)) {$x = $x + 1}
}
return $x;
}
This seems like such a long way of doing this, is there no simpler way?
Note: The isImage() function returns true if the file is an image.
Check out the Standard PHP Library (aka SPL) for DirectoryIterator:
$dir = new DirectoryIterator('/path/to/dir');
foreach($dir as $file ){
$x += (isImage($file)) ? 1 : 0;
}
(FYI there is an undocumented function called iterator_count() but probably best not to rely on it for now I would imagine. And you'd need to filter out unseen stuff like . and .. anyway.)
This will give you the count of what is in your dir. I'll leave the part about counting only images to you as I am about to fallll aaasssllleeelppppppzzzzzzzzzzzzz.
iterator_count(new DirectoryIterator('path/to/dir/'));
i do it like this:
$files = scandir($dir);
$x = count($files);
echo $x;
but it also counts the . and ..
The aforementioned code
$count = count(glob("*.{jpg,png,gif,bmp}"));
is your best best, but the {jpg,png,gif} bit will only work if you append the GLOB_BRACE flag on the end:
$count = count(glob("*.{jpg,png,gif,bmp}", GLOB_BRACE));
you could use glob...
$count = 0;
foreach (glob("*.*") as $file) {
if (isImage($file)) ++$count;
}
or, I'm not sure how well this would suit your needs, but you could do this:
$count = count(glob("*.{jpg,png,gif,bmp}"));
You could also make use of the SPL to filter the contents of a DirectoryIterator using your isImage function by extending the abstract FilterIterator class.
class ImageIterator extends FilterIterator {
public function __construct($path)
{
parent::__construct(new DirectoryIterator($path));
}
public function accept()
{
return isImage($this->getInnerIterator());
}
}
You could then use iterator_count (or implement the Countable interface and use the native count function) to determine the number of images. For example:
$images = new ImageIterator('/path/to/images');
printf('Found %d images!', iterator_count($images));
Using this approach, depending on how you need to use this code, it might make more sense to move the isImage function into the ImageIterator class to have everything neatly wrapped up in one place.
I use the following to get the count for all types of files in one directory in Laravel
$dir = public_path('img/');
$files = glob($dir . '*.*');
if ( $files !== false )
{
$total_count = count( $files );
return $totalCount;
}
else
{
return 0;
}
Your answer seems about as simple as you can get it. I can't think of a shorter way to it in either PHP or Perl.
You might be able to a system / exec command involving ls, wc, and grep if you are using Linux depending how complex isImage() is.
Regardless, I think what you have is quite sufficient. You only have to write the function once.
I use this to return a count of ALL files in a directory except . and ..
return count(glob("/path/to/file/[!\.]*"));
Here is a good list of glob filters for file matching purposes.
$nfiles = glob("/path/to/file/[!\\.]*");
if ($nfiles !== FALSE){
return count($nfiles);
} else {
return 0;
}

Categories