I'd like to make a gallery of all images i have under my domain (my internet root folder). All these images are in different folders. What's the best way to 'browse' through all the folders and return the images?
Use Google Image Search with site: www.mydomainwithimages.com as the search term and this will show you all your indexed images. This should be everything in your domain as long as your robots.txt file doesn't exclude the Google crawler.
Take a look at opendir you would want to write a function that gets called in a recursive loop, the function could loop through the files in the specific directory, check the file extension and return the files as an array which you would merge with a global array.
Depends on hosting system, you could use command line with exec or passthru
find /path/to/website/root/ -type f -name '*.jpg'
If you can't do such a thing, as fire said, opendir is the way to go.
I would give PHP's DirectoryIterator a spin.
This is untested pseudo-code, but it should work a little bit like this:
function scanDirectoryForImages($dirPath)
{
$images = array();
$dirIter = new DirectoryIterator($dirPath);
foreach($dirIter as $fileInfo)
{
if($fileInfo->isDot())
continue;
// If it's a directory, scan it recursively
elseif($fileInfo->isDir())
{
$images = array_merge(
$images, scanDirectoryForImages($fileInfo->getPath())
);
}
elseif($fileInfo->isFile())
{
/* This works only for JPEGs, oviously, but feel free to add other
extensions */
if(strpos($fileInfo->getFilename(), '.jpg') !== FALSE)
{
$images[] = $fileInfo->getPathname();
}
}
}
return $images;
}
Please don't sue me if this doesn't work, it's really kinda from the top of my hat, but using such a function would be the most elegant way to solve your problem, imho.
// edit: Yeah, that's basically the same as fire pointed out.
Related
I am creating a WordPress plugin which allows a user to apply sorting rules to a particular template (page, archive, single etc). I am populating list of pages using PHP scandir like so:
$files = scandir(get_template_directory());
The problem is that I keep single.php templates in a '/single' subfolder so these templates are not being called by the above function.
How can I use multiple directories within the scandir function (perhaps an array?) or will I need a different solution?
So basically I am trying to:
$files = scandir( get_template_directory() AND get_template_directory().'/single' );
My current solution (not very elegant as it requires 2 for each loops):
function query_caller_is_template_file_get_template_files()
{
$template_files_list = array();
$files = scandir(get_template_directory());
$singlefiles = scandir(get_template_directory().'/single');
foreach($files as $file)
{
if(strpos($file, '.php') === FALSE)
continue;
$template_files_list[] = $file;
}
foreach($singlefiles as $singlefile)
{
if(strpos($file, '.php') === FALSE)
continue;
$template_files_list[] = $singlefile;
}
return $template_files_list;
}
First, there's not really anything wrong about what you're doing. You have two directories, so you do the same thing twice. Of course you could make it look a little cleaner and avoid the blatant copy paste:
$files = array_merge(
scandir(get_template_directory()),
scandir(get_template_directory().'/single')
);
Now just iterate over the single array.
In your case, getting the file list recursively doesn't make sense, as there may be subdirectories you don't want to check. If you did want to recurse into subdirectories, opendir() and readdir() along with is_dir() would allow you to build a recursive scan function.
You could event tighten up the '.php' filter part a bit with array_filter().
$files = array_filter($files, function($file){
return strpos($file, '.php');
});
Here I'm assuming that should a file start with .php you're not really interested in it making your list (as strpos() will return the falsy value of 0 in that case). I'm also assuming that you're sure there will be no files that have .php in the middle somewhere.
Like, template.php.bak, because you'll be using version control for something like that.
If however there is the chance of that, you may want to tighten up your check a bit to ensure the .php is at the end of the filename.
I need to run a check on a folder to see when it was last modified. By this I mean the last time it, or any of the files it contains where last modified.
I have tried two ways so far:
using the stat() function on the folder, and then grabbing mtime
$stat = stat("directory/path/");
echo $stat["mtime"];
using the filemtime() function on the folder
echo (filemtime("directory/path/"));
Both of these methods return the same value, and this value does not change if I update one of the files. I am guessing this is because the folder structure itself does not change, only the content of one of the files.
I guess I could loop through all the files in the directory and check their modification dates, but there are potentially a lot of files and this doesn't seem very efficient.
Can anyone suggest how I might go about getting a last modification time for a folder and its content in an efficient way?
moi.
I suggest that you loop all files using foreach function and use it, i think there's no function for that purpose. Here's very simple example using that loop:
$directory = glob('gfd/*');
foreach ($directory as $file) {
$mdtime = date('d.m.Y H:i:s', filemtime($file));
}
echo "Folder last modified: $mdtime<br />";
Keep in mind that foreach is pretty fast, and if you have files < 3000, i think there's nothing to worried about. If you don't want to use this, you can always save modification date to file or something like that. :)
Subfolder-compatibility:
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;
}
See this question: php glob - scan in subfolders for a file
I have two folders, in one i have the videos and in the second one the configuration files for each video(3 files per video). Now if i want to delete a video i have to delete files by hand.
I found this :
<?php
$filename = 'name.of.the.video.xml';
$term = str_replace(".xml","", $filename);
$dirPath = ("D:/test/");
foreach (glob($dirPath.$term.".*") as $removeFile)
{
unlink ($removeFile);
}
?>
A echo will return:
D:/test/name.of.the.video.jpg
D:/test/name.of.the.video.srt
D:/test/name.of.the.video.xml
Is ok and it help me a lot, but i have a problem here.
Not all files are the same ex:
Name.of.The.video.jpg
Name.Of.The.Video.xml
If i echo the folder looking for that string and is not identic with the $filename will return empty.
So, my question is, how can i make that search Case insensitive?
Thank you.
You are making use of the glob function which is case sensitive. You are using the wrong function therefore to get the list of files.
You should therefore first normalize the filenames in the directory so they all share the same case (e.g. all lowercase). Or you need to use another method to get the directory listing case-insensitive. I suggest the first, however if that is not an option, why don't you glob for all files first and then filter the list of files using preg_grep which allows to specify patterns that are case-insensitive?
Which leads me to the point that it's more practicable to use DirectoryIterator with a RegexIterator:
$filename = 'name.of.the.video.xml';
$term = basename($filename, ".xml");
$files = new DirectoryIterator($dirPath);
$filesFiltered = new RegexIterator($files, sprintf('(^%s\\..*$)i', preg_quote($term)));
foreach($filesFiltered as $file)
{
printf("delete: %s\n", $file);
unlink($file->getPathname());
}
A good example of the flexibility of the Iterators code are your changed requirements: Do that for two directories at once. You just create two DirectoryIterators and append the one to the other with an AppendIterator. Job done. The rest of the code stays the same:
...
$files = new AppendIterator();
$files->append(new DirectoryIterator($dirPath1));
$files->append(new DirectoryIterator($dirPath2));
...
Voilá. Sounds good? glob is okay for some quick jobs that need just it. For everything else with directory operations start to consider the SPL. It has much more power.
Is strcasecmp() a valid function for this? Its a case insensitive str comparison function?
Surely if you know the file name and you can echo it out, you can pass this to unlink()?
I want to delete cache files in a directory, the directory can contain up to 50.000 files. I currently I use this function.
// Deletes all files in $type directory that start with $start
function clearCache($type,$start)
{
$open = opendir($GLOBALS['DOC_ROOT']."/cache/".$type."/");
while( ($file = readdir($open)) !== false )
{
if ( strpos($file, $start)!==false )
{
unlink($GLOBALS['DOC_ROOT']."/cache/".$type."/".$file);
}
}
closedir($open);
}
This works fine and it is fast, but is there any faster way to do this? (scan_dir seems to be slow). I can move the cache to memory obviously.
Thanks,
hamlet
You may want to take a look into the glob function, as it may be even faster... it depends on the C library's glob command to do its work.
I haven't tested this, but I think this would work::
foreach (glob($GLOBALS['DOC_ROOT']."/cache/".$type."/".$start) as $file) {
unlink($GLOBALS['DOC_ROOT']."/cache/".$type."/".$file);
}
Edit: I'm not sure if $file would be just the filename or the entire path. glob's documentation implies just the filename.
Either glob as suggested before or, if you can be certain there won't be malicious input, by issueing directly to the system via exec(sprintf('rm %s/sess*', realpath($path)));, which should be fastest.
I'm trying to design a program in PHP that would allow me to find files with specific file extensions (example .jpg, .shp etc) in a known directory which consists of multiple folders.
Sample code, documentation or information about what methods I will be required to use will be much appreciated.
glob is pretty easy:
<?php
foreach (glob("*.txt") as $filename) {
echo "$filename size " . filesize($filename) . "\n";
}
?>
There are a few suggestions for recursive descent at the readdir page.
Take a look at PHP's SPL DirectoryIterator.
I believe PHP's glob() function is exactly what you are looking for:
http://php.net/manual/en/function.glob.php
Use readdir to get a list of files, and fnmatch to work out if it matches your required filename pattern. Do all this inside a function, and call your function when you find directories. Ask another question if you get stuck implementing this (or comment if you really have no idea where to start).
glob will get you all the files in a given directory, but not the sub directories. If you need that too, you will need to: 10. get recursive, 20. goto 10.
Here's the pseudo pseudocode:
function getFiles($pattern, $dir) {
$files = glob($dir . $pattern);
$folders = glob($dir, GLOB_ONLYDIR);
foreach ($folders as $folder) {
$files = $files + getFiles($folder);
}
return $files;
}
The above will obviously need to be tweaked to get it working, but hopefully you get the idea (remember not to follow directory links to ".." or "." or you'll be in infinite loop town).