This question already has answers here:
How do I recursively delete a directory and its entire contents (files + sub dirs) in PHP? [duplicate]
(21 answers)
Closed 9 years ago.
Suppose, I have a directory named "temp" which have a lot of trash files which are generated automatically. How do I clear/empty the "temp" directory every once a week automatically using PHP? I don't know what files are in there. I just want to empty the directory.
You can use a code snippet like this and if your application is on a Linux based system then run a cron job.
$files = glob('path/to/folder/*'); // get all file names present in folder
foreach($files as $file){ // iterate files
if(is_file($file))
unlink($file); // delete the file
}
First of all you need cron job and php script to erase the files.
Here php script:
$fileToDelete = glob('path/to/temp/*');
foreach($fileToDelete as $file){
if(is_file($file))
unlink($file);
}
After that you need to configure cron to execute this file, for example every day or as you want:
0 0 * * 0 /path/script.php //will execute every week
Use a cron to call a script that will delete the entire folder, then mkdir it again.
Give the path of your folder in $path
$path = $_SERVER['DOCUMENT_ROOT'].'/work/removegolder/'; // path of your directory
header( 'Content-type: text/plain' ); // plain text for easy display
// preconditon: $dir ends with a forward slash (/) and is a valid directory
// postcondition: $dir and all it's sub-directories are recursively
// searched through for .svn directories. If a .svn directory is found,
// it is deleted to remove any security holes.
function removeSVN( $dir ) {
//echo "Searching: $dir\n\t";
$flag = false; // haven't found .svn directory
$svn = $dir . 'foldername';
if( is_dir( $svn ) ) {
if( !chmod( $svn, 0777 ) )
echo "File permissions could not be changed (this may or may not be a problem--check the statement below).\n\t"; // if the permissions were already 777, this is not a problem
delTree( $svn ); // remove the directory with a helper function
if( is_dir( $svn ) ) // deleting failed
echo "Failed to delete $svn due to file permissions.";
else
echo "Successfully deleted $svn from the file system.";
$flag = true; // found directory
}
if( !$flag ) // no .svn directory
echo 'No directory found.';
echo "\n\n";
$handle = opendir( $dir );
while( false !== ( $file = readdir( $handle ) ) ) {
if( $file == '.' || $file == '..' ) // don't get lost by recursively going through the current or top directory
continue;
if( is_dir( $dir . $file ) )
removeSVN( $dir . $file . '/' ); // apply the SVN removal for sub directories
}
}
// precondition: $dir is a valid directory
// postcondition: $dir and all it's contents are removed
// simple function found at http://www.php.net/manual/en/function.rmdir.php#93836
function delTree( $dir ) {
$files = glob( $dir . '*', GLOB_MARK ); // find all files in the directory
foreach( $files as $file ) {
if( substr( $file, -1 ) == '/')
delTree( $file ); // recursively apply this to sub directories
else
unlink( $file );
}
if ( is_dir( $dir ) ){
//echo $dir;
// die;
//rmdir( $dir ); // remove the directory itself (rmdir only removes a directory once it is empty)
}
}
// remove all directories in the
// current directory and sub directories
// (recursively applied)
removeSVN($path);
Related
I'm creating a little class which allows to resize a gif. To do that I create a temporary directory with all frames, resize them and then create my gif again.
Once my gif is created, i want to delete my temporary directory. But once all my files deleted, I got the following errors :
Warning: Directory not empty
Here is my code :
private function remove_temp_dir() {
$handle = opendir( $this->temp_folder_path );
foreach ( $this->frames as $path => $duration ) {
unlink( $path );
}
closedir( $handle );
var_dump( scandir( $this->temp_folder_path ) );
var_dump( $this->temp_folder_path . 'temp-102.gif' );
var_dump( file_exists( $this->temp_folder_path . 'temp-102.gif' ) );
rmdir( $this->temp_folder_path );
}
Here is what i get :
As you can see, there is no hidding files because the scandir didn't return any.
As you can see, i tried this solution but didn't work.
I can manually remove it, there is no files inside once the code done.
I can remove it in code afterwards (once my page is reload etc...).
I tried a sleep() it didn't work.
For other informations :
I used this library to decode the GIF into several image.
I used this code to resize the image.
Thanks,
For remove none-empty directory, You should use recursive directory deletion functions.
public function rrmdir($path) {
$iterator = new DirectoryIterator($path);
foreach ($iterator as $fileInfo) {
if ($fileInfo->isDot() || !$fileInfo->isDir()) {
continue;
}
rrmdir($fileInfo->getPathname());
}
$files = new FilesystemIterator($path);
/* #var SplFileInfo $file */
foreach ($files as $file) {
unlink($file->getPathname());
}
return rmdir($path);
}
I want to extract only images from a zip file but i also want it to extract images that are found in subfolders as well.How can i achieve this based on my code below.Note: i am not trying to preserve directory structure here , just want to extract any image found in zip.
//extract files in zip
for ($i = 0; $i < $zip->numFiles; $i++) {
$file_name = $zip->getNameIndex($i);
$file_info = pathinfo($file_name);
//if ( substr( $file_name, -1 ) == '/' ) continue; // skip directories - need to improve
if (in_array($file_info['extension'], $this->config->getValidExtensions())) {
//extract only images
copy("zip://" . $zip_path . "#" . $file_name, $this->tmp_dir . '/images/' . $file_info['basename']);
}
}
$zip->close();
Edit
My code works fine all i need to know is how to make ziparchive go in subdirectories as well
Your code is correct. I have created a.zip with files a/b/c.png, d.png:
$ mkdir -p a/b
$ zip -r a.zip d.png a
adding: d.png (deflated 4%)
adding: a/ (stored 0%)
adding: a/b/ (stored 0%)
adding: a/b/c.png (deflated 8%)
$ unzip -l a.zip
Archive: a.zip
Length Date Time Name
--------- ---------- ----- ----
122280 11-05-2016 14:45 d.png
0 11-05-2016 14:44 a/
0 11-05-2016 14:44 a/b/
36512 11-05-2016 14:44 a/b/c.png
--------- -------
158792 4 files
The code extracted both d.png and c.png from a.zip into the destination directory:
$arch_filename = 'a.zip';
$dest_dir = './dest';
if (!is_dir($dest_dir)) {
if (!mkdir($dest_dir, 0755, true))
die("failed to make directory $dest_dir\n");
}
$zip = new ZipArchive;
if (!$zip->open($arch_filename))
die("failed to open $arch_filename");
for ($i = 0; $i < $zip->numFiles; ++$i) {
$path = $zip->getNameIndex($i);
$ext = pathinfo($path, PATHINFO_EXTENSION);
if (!preg_match('/(?:jpg|png)/i', $ext))
continue;
$dest_basename = pathinfo($path, PATHINFO_BASENAME);
echo $path, PHP_EOL;
copy("zip://{$arch_filename}#{$path}", "$dest_dir/{$dest_basename}");
}
$zip->close();
Testing
$ php script.php
d.png
a/b/c.png
$ find ./dest -type f
./dest/d.png
./dest/c.png
So the code is correct, and the issue must be somewhere else.
Based upon file extension ( not necessarily the most reliable method ) you might find the following helpful.
/* source zip file and target location for extracted files */
$file='c:/temp2/experimental.zip';
$destination='c:/temp2/extracted/';
/* Image file extensions to allow */
$exts=array('jpg','jpeg','png','gif','JPG','JPEG','PNG','GIF');
$files=array();
/* create the ZipArchive object */
$zip = new ZipArchive();
$status = $zip->open( $file, ZIPARCHIVE::FL_COMPRESSED );
if( $status ){
/* how many files are in the archive */
$count = $zip->numFiles;
for( $i=0; $i < $count; $i++ ){
try{
$name = $zip->getNameIndex( $i );
$ext = pathinfo( $name, PATHINFO_EXTENSION );
$basename = pathinfo( $name, PATHINFO_BASENAME );
/* store a reference to the file name for extraction or copy */
if( in_array( $ext, $exts ) ) {
$files[]=$name;
/* To extract files and ignore directory structure */
$res = copy( 'zip://'.$file.'#'.$name, $destination . $basename );
echo ( $res ? 'Copied: '.$basename : 'unable to copy '.$basename ) . '<br />';
}
}catch( Exception $e ){
echo $e->getMessage();
continue;
}
}
/* To extract files, with original directory structure, uncomment below */
if( !empty( $files ) ){
#$zip->extractTo( $destination, $files );
}
$zip->close();
} else {
echo $zip->getStatusString();
}
This will allow for you traverse all of the directories in a path and will search for anything that is an image/has the extensions that you have defined. Since you told the other use that you have the ziparchive portion done I have omitted that...
<?php
function traverse($path, $images = [])
{
$files = array_diff(scandir($path), ['.', '..']);
foreach ($files as $file) {
// check if the file is an image
if (in_array(strtolower(pathinfo($file, PATHINFO_EXTENSION)), ['jpg', 'jpeg', 'png', 'gif'])) {
$images[] = $file;
}
if (is_dir($path . '/' . $file)) {
$images = traverse($path . '/' . $file, $images);
}
}
return $images;
}
$images = traverse('/Users/kyle/Downloads');
You want to follow this process:
Get all of the files in the current working directory
If a file in the CWD is an image add it to the images array
If a file in the CWD is a directory, recursively call the traverse function and looking for images in the directory
In the new CWD look for images, if the file is a directory recurse, etc...
It is important to keep track of the current path so you're able to call is_dir on the file. Also you want to make sure not to search '.' or '..' or you will never hit the base recursion case/it will be infinite.
Also this will not keep the directory path for the image! If you want to do that you should do $image[] = $path . '/' . $file;. You may want to do that and then get all of the file contents wants the function finishes running. I wouldn't recommend sorting the contents in the $image array because it could use an absurd amount of memory.
First thing to follow a folder is to regard it - your code does not do this.
There are no folders in a ZIP (in fact, even in the file system a "folder" IS a file, just a special one). The file (data) has a name, maybe containing a path (most likely a relative one). If by "go in subdiectories" means, that you want the same relative folder structure of the zipped files in your file system, you must write code to create these folders. I think copy won't do that for you automatically.
I modified your code and added the creation of folders. Mind the config variables I had to add to make it runable, configure it to your environment. I also left all my debug output in it. Code works for me standalone on Windows 7, PHP 5.6
error_reporting(-1 );
ini_set('display_errors', 1);
$zip_path = './test/cgiwsour.zip';
$write_dir = './test'; // base path for output
$zip = new ZipArchive();
if (!$zip->open($zip_path))
die('could not open zip file '.PHP_EOL);
$valid_extensions = ['cpp'];
$create_subfolders = true;
//extract files in zip
for ($i = 0; $i < $zip->numFiles; $i++) {
$file_name = $zip->getNameIndex($i);var_dump($file_name, $i);
$file_info = pathinfo($file_name);//print_r($file_info);
//if ( substr( $file_name, -1 ) == '/' ) continue; // skip directories - need to improve
if (isset($file_info['extension']) && in_array(strtolower($file_info['extension']), $valid_extensions)) {
$tmp_dir = $write_dir;
if ($create_subfolders) {
$dir_parts = explode('/', $file_info['dirname']);
print_r($dir_parts);
foreach($dir_parts as $folder) {
$tmp_dir = $tmp_dir . '/' . $folder;
var_dump($tmp_dir);
if (!file_exists($tmp_dir)) {
$res = mkdir($tmp_dir);
var_dump($res);
echo 'created '.$tmp_dir.PHP_EOL;
}
}
}
else {
$tmp_dir .= '/' . $file_info['dirname'];
}
//extract only images
$res = copy("zip://" . $zip_path . "#" . $file_name, $tmp_dir . '/' . $file_info['basename']);
echo 'match : '.$file_name.PHP_EOL;
var_dump($res);
}
}
$zip->close();
Noticeable is, that mkdir() calls may not work flawlessly on all systems due to access/rights restrictions.
by mistaken I upload my code on server with svn files and folders. I don't have access for SSH so can't run commands.
so is there any php code by using which I can delete all .svn folders from my projects.
EDIT:
Finding all the .svn folders is a complicated process to do that you need a to use recursive functions.
Link to code: http://pastebin.com/i5QMGm1C
Or view it here:
function rrmdir($dir)
{
foreach(glob($dir . '/*') as $path) {
if(is_dir($path)){
rrmdir($path);
}
else{
unlink($path);
}
}
foreach(glob($dir . '/.*') as $path) {
if(is_dir($path)){
$base_name = basename($path);
if ($base_name != '..' && $base_name != '.'){
rrmdir($path);
}
}
else{
unlink($path);
}
}
rmdir($dir);
}
function delete_dir($base, $dir)
{
static $count = 0;
foreach (glob($base . '/*') as $path){
if(is_dir($path)){
delete_dir($path, $dir);
}
}
foreach (glob($base . '/.*') as $path){
if(is_dir($path)){
$base_name = basename($path);
if ($base_name != '..' && $base_name != '.'){
if ($base_name == $dir){
rrmdir($path);
echo 'Directory (' . $path . ') Removed!<br />';
$count++;
}
else {
delete_dir($path, $dir);
}
}
}
}
return $count;
}
$base = $_SERVER['DOCUMENT_ROOT'];
$dir = '.svn';
$count = delete_dir($base, $dir);
echo 'Total: ' . $count . ' Folders Removed!';
I get a solution here it is
copied from lateralcode with little modification
$path = $_SERVER['DOCUMENT_ROOT'].'/work/remove-svn-php/'; // path of your directory
header( 'Content-type: text/plain' ); // plain text for easy display
// preconditon: $dir ends with a forward slash (/) and is a valid directory
// postcondition: $dir and all it's sub-directories are recursively
// searched through for .svn directories. If a .svn directory is found,
// it is deleted to remove any security holes.
function removeSVN( $dir ) {
//echo "Searching: $dir\n\t";
$flag = false; // haven't found .svn directory
$svn = $dir . '.svn';
if( is_dir( $svn ) ) {
if( !chmod( $svn, 0777 ) )
echo "File permissions could not be changed (this may or may not be a problem--check the statement below).\n\t"; // if the permissions were already 777, this is not a problem
delTree( $svn ); // remove the .svn directory with a helper function
if( is_dir( $svn ) ) // deleting failed
echo "Failed to delete $svn due to file permissions.";
else
echo "Successfully deleted $svn from the file system.";
$flag = true; // found directory
}
if( !$flag ) // no .svn directory
echo 'No .svn directory found.';
echo "\n\n";
$handle = opendir( $dir );
while( false !== ( $file = readdir( $handle ) ) ) {
if( $file == '.' || $file == '..' ) // don't get lost by recursively going through the current or top directory
continue;
if( is_dir( $dir . $file ) )
removeSVN( $dir . $file . '/' ); // apply the SVN removal for sub directories
}
}
// precondition: $dir is a valid directory
// postcondition: $dir and all it's contents are removed
// simple function found at http://www.php.net/manual/en/function.rmdir.php#93836
function delTree( $dir ) {
$files = glob( $dir . '*', GLOB_MARK ); // find all files in the directory
foreach( $files as $file ) {
if( substr( $file, -1 ) == '/')
delTree( $file ); // recursively apply this to sub directories
else
unlink( $file );
}
if ( is_dir( $dir ) ){
//echo $dir;
// die;
rmdir( $dir ); // remove the directory itself (rmdir only removes a directory once it is empty)
}
}
// remove all .svn directories in the
// current directory and sub directories
// (recursively applied)
removeSVN($path);
I've just watched these videos on displaying images from a directory and would like some help modifiying the code.
http://www.youtube.com/watch?v=dHq1MNnhSzU - part 1
http://www.youtube.com/watch?v=aL-tOG8zGcQ -part 2
What the videos show is almost exactly what I wanted, but the system I have in mind is for photo galleries.
I plan on having a folder called galleries, which will contain other folders, one each for each different photo sets ie
Galleries
Album 1
Album 2
I would like some help to modify the code so that it can identify and display only the directories on one page. That way I can convert those directories into links that take you to the albums themselves, and use the orignal code to pull the images in from there.
For those that want the video code, here it is
$dir = 'galleries';
$file_display = array('bmp', 'gif', 'jpg', 'jpeg', 'png');
if (file_exists($dir) == false) {
echo 'Directory \'', $dir , '\' not found!';
} else {
$dir_contents = scandir($dir);
foreach ($dir_contents as $file) {
$file_type = strtolower(end(explode('.', $file)));
if ($file !== '.' && $file !== '..' && in_array($file_type, $file_display) == true) {
echo '<img src="', $dir, '/', $file, '" alt="', $file, '" />';
}
}
}
You need to use a function like this to list all of the directories:
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 {
echo "$spaces $file<br />";
// Just print out the filename
}
}
}
closedir( $dh );
// Close the directory handle
}
Then, pass the directory a user selected in as your $dir variable to the function you currently have.
I can't test any code right now but would love to see a solution here along the lines of:
$directory = new RecursiveDirectoryIterator('path/galleries');
$iterator = new RecursiveIteratorIterator($directory);
$regex = new RegexIterator($iterator, '/^.+\.(bmp|gif|jpg|jpeg|png)$/i', RecursiveRegexIterator::GET_MATCH);
SPL is powerful and should be used more.
The RecursiveDirectoryIterator provides an interface for iterating recursively over filesystem directories.
http://www.php.net/manual/en/class.recursivedirectoryiterator.php
Has anyone had any experience with deleting the __MACOSX folder with PHP?
The folder was generated after I unzipped an archive, but I can't seem to do delete it.
The is_dir function returns false on the file, making the recursive delete scripts fail (because inside the archive is the 'temp' files) so the directory isn't empty.
I'm using the built-in ZipArchive class (extractTo method) in PHP5.
The rmdir script I'm using is one I found on php.net:
<?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 found an improved version of the function from http://www.php.net/rmdir that requires PHP5.
This function uses DIRECTORY_SEPARATOR instead of /. PHP defines DIRECTORY_SEPARATOR as the proper character for the running OS ('/' or '\').
The Directory Location doesn't need to end with a slash.
The function returns true or false on completion.
function deleteDirectory($dir) {
if (!file_exists($dir)) return true;
if (!is_dir($dir)) return unlink($dir);
foreach (scandir($dir) as $item) {
if ($item == '.' || $item == '..') continue;
if (!deleteDirectory($dir.DIRECTORY_SEPARATOR.$item)) return false;
}
return rmdir($dir);
}
Which OS and version are you using?
You need to correct the paths to the directory and files.
// ensure $dir ends with a slash
function delTree($dir) {
foreach( $files as $file ){
if( substr( $file, -1 ) == '/' )
delTree( $dir.$file );
else
unlink( $dir.$file );
}
rmdir( $dir );
}