I am new to php and trying to learn how to navigate a local file structure in for the format:
-Folder
-SubFolder
-SubSubFolder
-SubSubFolder
-SubFolder
-SubSubFolder
...
From another stackoverflow question I have been able to use this code using scandir():
<?php
$scan = scandir('Folder');
foreach($scan as $file)
{
if (!is_dir($file))
{
$str = "Folder/".$file;
echo $str;
}
}
?>
This allows me to generate a list of strings of all the 'SubFolder' in my folder directory.
What I am trying to do is list all the 'SubSubFolder' in each 'SubFolder', so that I can create a string of the 'SubSubFolder' name in combination with its 'SubFolder' parent and add it to an array.
<?php
$scan = scandir('Folder');
foreach($scan as $file)
{
if (!is_dir($file))
{
$str = "Folder/".$file;
//echo $str;
$scan2 = scandir($str);
foreach($scan2 as $file){
if (!is_dir($file))
{
echo "Folder/SubFolder/".$file;
}
}
}
}
?>
This however isn't working, and I wasn't sure if it was because I cannot do consecutive scandir() or if I cannot use $file again.
There is probably a better solution, but hopefully the following will be of some help.
<?php
function getDirectory( $path = '.', $level = 0 ){
$ignore = array( 'cgi-bin', '.', '..' );
// Directories to ignore when listing output. Many hosts
// will deny PHP access to the cgi-bin.
$dh = #opendir( $path );
// Open the directory to the handle $dh
while( false !== ( $file = readdir( $dh ) ) ){
// Loop through the directory
if( !in_array( $file, $ignore ) ){
// Check that this file is not to be ignored
$spaces = str_repeat( ' ', ( $level * 4 ) );
// Just to add spacing to the list, to better
// show the directory tree.
if( is_dir( "$path/$file" ) ){
// Its a directory, so we need to keep reading down...
echo "<strong>$spaces -$file</strong><br />";
getDirectory( "$path/$file", ($level+1) );
// Re-call this same function but on a new directory.
// this is what makes function recursive.
} else {
//To list folders names only and not the files within comment out the following line.
echo "$spaces $file<br />.";
// Just print out the filename
}
}
}
closedir( $dh );
// Close the directory handle
}
getDirectory( "folder" );
// Get the current directory
?>
Related
I am currently trying to make a script that will find images with *.jpg / *.png extensions in directories and subdirectories.
If some picture with one of these extensions is found, then save it to an array with path, name, size, height and width.
So far I have this piece of code, which will find all files, but I don't know how to get only jpg / png images.
class ImageCheck {
public static function getDirectory( $path = '.', $level = 0 ){
$ignore = array( 'cgi-bin', '.', '..' );
// Directories to ignore when listing output.
$dh = #opendir( $path );
// Open the directory to the handle $dh
while( false !== ( $file = readdir( $dh ) ) ){
// Loop through the directory
if( !in_array( $file, $ignore ) ){
// Check that this file is not to be ignored
$spaces = str_repeat( ' ', ( $level * 4 ) );
// Just to add spacing to the list, to better
// show the directory tree.
if( is_dir( "$path/$file" ) ){
// Its a directory, so we need to keep reading down...
echo "<strong>$spaces $file</strong><br />";
ImageCheck::getDirectory( "$path/$file", ($level+1) );
// Re-call this same function but on a new directory.
// this is what makes function recursive.
} else {
echo "$spaces $file<br />";
// Just print out the filename
}
}
}
closedir( $dh );
// Close the directory handle
}
}
I call this function in my template like this
ImageCheck::getDirectory($dir);
Save a lot of headache and just use PHP's built in recursive search with a regex expression:
<?php
$Directory = new RecursiveDirectoryIterator('path/to/project/');
$Iterator = new RecursiveIteratorIterator($Directory);
$Regex = new RegexIterator($Iterator, '/^.+(.jpe?g|.png)$/i', RecursiveRegexIterator::GET_MATCH);
?>
In case you are not familiar with working with objects, here is how to iterate the response:
<?php
foreach($Regex as $name => $Regex){
echo "$name\n";
}
?>
How to use php keep only specific file and remove others in directory?
example:
1/1.png, 1/2.jpeg, 1/5.png ...
the file number, and file type is random like x.png or x.jpeg, but I have a string 2.jpeg the file need to keep.
any suggestion how to do this??
Thanks for reply, now I coding like below but the unlink function seems not work delete anything.. do I need change some setting? I'm using Mamp
UPDATE
// explode string <img src="u_img_p/5/x.png">
$content_p_img_arr = explode('u_img_p/', $content_p_img);
$content_p_img_arr_1 = explode('"', $content_p_img_arr[1]); // get 5/2.png">
$content_p_img_arr_2 = explode('/', $content_p_img_arr_1[0]); // get 5/2.png
print $content_p_img_arr_2[1]; // get 2.png < the file need to keep
$dir = "u_img_p/".$id;
if ($opendir = opendir($dir)){
print $dir;
while(($file = readdir($opendir))!= FALSE )
if($file!="." && $file!= ".." && $file!= $content_p_img_arr_2[1]){
unlink($file);
print "unlink";
print $file;
}
}
}
I change the code unlink path to folder, then it works!!
unlink("u_img_p/".$id.'/'.$file);
http://php.net/manual/en/function.scandir.php
This will get all files in a directory into an array, then you can run a foreach() on the array and look for patterns / matches on each file.
unlink() can be used to delete the file.
$dir = "/pathto/files/"
$exclude[] = "2.jpeg";
foreach(scandir($dir) as $file) {
if (!in_array($file, $exclude)) {
unlink("$dir/$file");
}
}
Simple and to the point. You can add multiple files to the $exclude array.
$dir = "your_folder_path";
if ($opendir = opendir($dir)){
//read directory
while(($file = readdir($opendir))!= FALSE ){
if($file!="." && $file!= ".." && $file!= "2.jpg"){
unlink($file);
}
}
}
function remove_files( $folder_path , $aexcludefiles )
{
if (is_dir($folder_path))
{
if ($dh = opendir($folder_path))
{
while (($file = readdir($dh)) !== false)
{
if( $file == '.' || $file == '..' )
continue ;
if( in_array( $file , $aexcludefiles ) )
continue ;
$file_path = $folder_path."/".$file ;
if( is_link( $file_path ) )
continue ;
unlink( $file_path ) ;
}
closedir($dh);
}
}
}
$aexcludefiles = array( "2.jpeg" )
remove_files( "1" , $aexcludefiles ) ;
I'm surprised people don't use glob() more. Here is another idea:
$dir = '/absolute/path/to/u_img_p/5/';
$exclude[] = $dir . 'u_img_p/5/2.jpg';
$filesToDelete = array_diff(glob($dir . '*.jpg'), $exclude);
array_map('unlink', $filesToDelete);
First, glob() returns an array of files based on the pattern provided to it. Next, array_diff() finds all the elements in the first array that aren't in the second. Finally, use array_map() with unlink() to delete all but the excluded file(s). Be sure to use absolute paths*.
You could even make it into a helper function. Here's a start:
<?php
/**
* #param string $path
* #param string $pattern
* #param array $exclude
* #return bool
*/
function deleteFiles($path, $pattern, $exclude = [])
{
$basePath = '/absolute/path/to/your/webroot/or/images/or/whatever/';
$path = $basePath . trim($path, '/');
if (is_dir($path)) {
array_map(
'unlink',
array_diff(glob($path . '/' . $pattern, $exclude)
);
return true;
}
return false;
}
unlink() won't work unless the array of paths returned by glob() happen to be relative to where unlink() is called. Since glob() will return only what it matches, it's best to use the absolute path of the directory in which your files to delete/exclude are contained.See the docs and comments on how glob() matches and give it a play to see how it works.
Friends,
I have a problem............
Help me please........
Am getting the image url from my client, i want to store those images in my local folder.
if those images are in less, i will save them manually
But they are greater than 5000 images.........
Please give some code to down load all the images with PHP
you could try file_get_contents for this. just loop over the array of files and use file_get_contents('url'); to retrieve the files into a string and then file_put_contents('new file name'); to write the files again.
You may download file using file_get_contents() PHP function, and then write it on your local computer, for example, with fwrite() function.
The only opened question is, where to get list of files supposed to be downloaded - you did not specify it in your question.
Code draft:
$filesList = // obtain URLs list somehow
$targetDir = // specify target dir
foreach ($filesList: $fileUrl) {
$urlParts = explode("/", $fileUrl);
$name = $urlParts[count($urlParts - 1)];
$contents = file_get_contents($fileUrl);
$handle = fopen($targetDir.$filename, 'a');
fwrite($handle, $contents);
fclose($handle);
}
I'm not sure that this is what you want. Given a folder's (where PHP has the authority to get the folder's contents) URL and a URL you want to write to, this will copy all of the files:
function copyFilesLocally( $source, $target_folder, $index = 5000 )
{
copyFiles( glob( $source ), $target_folder, $index );
}
function copyFiles( array $files, $target_folder, $index )
{
if( count( $files ) > $index )
{
foreach( $files as $file )
{
copy( $file, $target_folder . filename( $file ) );
}
}
}
If you're looking to a remote server, try this:
function copyRemoteFiles( $directory, $target_folder, $exclutionFunction, $index = 5000)
{
$dom = new DOMDocument();
$dom->loadHTML( file_get_contents( $directory ) );
// This is a list of all links which is what is served up by Apache
// when listing a directory without an index.
$list = $dom->getElementsByTagName( "a" );
$images = array();
foreach( $list as $item )
{
$curr = $item->attributes->getNamedItem( "href" )->nodeValue;
if( $exclutionFunction( $curr ) )
$images[] = "$directory/$curr";
}
copyFiles( $images, $target_folder, $index );
}
function exclude_non_dots( $curr )
{
return strpos( $curr, "." ) != FALSE;
}
copyRemoteFiles( "http://example.com", "/var/www/images", "exclude_non_dots" );
How do I do that? Is there any method provided by kohana 3?
To delete a directory and all this content, you'll have to write some recursive deletion function -- or use one that already exists.
You can find some examples in the user's notes on the documentation page of rmdir ; for instance, here's the one proposed by bcairns in august 2009 (quoting) :
<?php
// ensure $dir ends with a slash
function delTree($dir) {
$files = glob( $dir . '*', GLOB_MARK );
foreach( $files as $file ){
if( substr( $file, -1 ) == '/' )
delTree( $file );
else
unlink( $file );
}
rmdir( $dir );
}
?>
I suggest this way, simple and direct.
$files = glob('your/folder/' . '*', GLOB_MARK);
foreach($files as $file)
{
if (is_dir($file)) {
self::deleteDir($file);
} else {
unlink($file);
}
}
have you tried unlink in the directory ?
chdir("file");
foreach (glob("N*") as $filename )
{
unlink($filename);
}
This deletes filenames starting from N
I'm not sure about Kohana 3, but I'd use a DirectoryIterator() and unlink() in conjunction.
The solution of Pascal does not work on all OS. Therefor I have created another solution. The code is part of a static class library and is static.
It deletes all files and directories in a given parent directory.
The function is recursive for the subdirectories and has an option not to delete the parent directory ($keepFirst).
If the parent directory does not exist or is not a directory 'null' is returned. In case of a successful deletion 'true' is returned.
/**
* Deletes all files in the given directory, also the subdirectories.
* #param string $dir Name of the directory
* #param boolean $keepFirst [Optional] indicator for first directory.
* #return null | true
*/
public static function deltree( $dir, $keepFirst = false ) {
// First check if it is a directory.
if (! is_dir( $dir ) ) {
return null;
}
if ($handle = opendir( $dir ) ) {
while (false !== ( $fileName = readdir($handle) ) ) {
// Skips the hidden directory files.
if ($fileName == "." || $fileName == "..") {
continue;
}
$dpFile = sprintf( "%s/%s", $dir, $fileName );
if (is_dir( $dpFile ) ) {
self::deltree( $dpFile );
} else {
unlink( $dpFile );
}
} // while
// Directory removal, optional not the parent directory.
if (! $keepFirst ) {
rmdir( $dir );
}
} // if
return true;
} // deltree
I have an array that lists folders in a directory. Until now, I've been hardcoding the folder names, but rather than do that, I thought I could easily create a script to parse the directory and just assign each folder name to the array. That way, I could easily add folders and not have to touch the script again...
The subject array creates an options list pulldown menu listing each folder...
Currently, the array is hardcoded like so...
"options" => array("folder one" => "folder1", "folder two" => "folder2")),
But I'm trying to make it dynamic based on whatever folders it finds in the given directory.
Here's the script I'm using to parse the directory and return the foldernames to the array. It works fine.
function getDirectory( $path = '.', $level = 0 )
{
// Directories to ignore when listing output.
$ignore = array( '.', '..' );
// Open the directory to the handle $dh
$dh = #opendir( $path );
// Loop through the directory
while( false !== ( $file = readdir( $dh ) ) )
{
// Check that this file is not to be ignored
if( !in_array( $file, $ignore ) )
{
// Show directories only
if(is_dir( "$path/$file" ) )
{
// Re-call this same function but on a new directory.
// this is what makes function recursive.
//echo $file." => ".$file. ", ";
// need to return the folders in the form expected by the array. Probably could just add the items directly to the array?
$mydir2=$mydir2.'"'.$file.'" => "'.$file. '", ';
getDirectory( "$path/$file", ($level+1) );
}
}
}
return $mydir2;
// Close the directory handle
closedir( $dh );
}
And here's my first take at getting those folders into the array...
$mydir = getDirectory('/images/');
"options" => array($mydir)),
But obviously, that doesn't work correctly since its not feeding the array properly I just get a string in my options list... I'm sure this is an easy conversion step I'm missing...
Why not just look at php.net? It has several examples on recursive dir listing.
Here is one example:
<?php
public static function getTreeFolders($sRootPath = UPLOAD_PATH_PROJECT, $iDepth = 0) {
$iDepth++;
$aDirs = array();
$oDir = dir($sRootPath);
while(($sDir = $oDir->read()) !== false) {
if($sDir != '.' && $sDir != '..' && is_dir($sRootPath.$sDir)) {
$aDirs[$iDepth]['sName'][] = $sDir;
$aDirs[$iDepth]['aSub'][] = self::getTreeFolders($sRootPath.$sDir.'/',$iDepth);
}
}
$oDir->close();
return empty($aDirs) ? false : $aDirs;
}
?>
You want to create an array, not a string.
// Replace
$mydir2=$mydir2.'"'.$file.'" => "'.$file. '", ';
// With
$mydir2[$file] = $file;
Also, close $dh before returning. Now, closedir is never called.
Here is a simple function that will return an array of available directories, but it is not recursive in that it has a limited depth. I like it because it is so simple:
<?php
function get_dirs( $path = '.' ){
return glob(
'{' .
$path . '/*,' . # Current Dir
$path . '/*/*,' . # One Level Down
$path . '/*/*/*' . # Two Levels Down, etc.
'}', GLOB_BRACE + GLOB_ONLYDIR );
}
?>
You can use it like this:
$dirs = get_dirs( WP_CONTENT_DIR . 'themes/clickbump_wp2/images' );
If you're using PHP5+ you might like scandir(), which is a built-in function that seems to do pretty much what you're after. Note that it lists all the entries in a folder - files, folders, . and .. included.