I want to delete files in a specific directory in PHP. How can I achieve this?
I have the following code but it does not delete the files.
$files = array();
$dir = dir('files');
while ($file = $dir->read()) {
if ($file != '.' && $file != '..') {
$files[] = $file;
}
unlink($file);
}
I think your question isn't specific, this code must clear all files in the directory 'files'.
But there are some errors in that code I think, and here is the right code:
$files= array();
$dir = dir('files');
while (($file = $dir->read()) !== false) { // You must supply a condition to avoid infinite looping
if ($file != '.' && $file != '..') {
$files[] = $file; // In this array you push the valid files in the provided directory, which are not (. , ..)
}
unlink('files/'.$file); // This must remove the file in the queue
}
And finally make sure that you provided the right path to dir().
You can get all directory contents with glob and check if the value is a file with is_file() before unlinking it.
$files = glob('files/*'); // get directory contents
foreach ($files as $file) { // iterate files
// Check if file
if (is_file($file)) {
unlink($file); // delete file
}
}
If you want to remove files matching a pattern like .png or .jpg, you have to use
$files = glob('/tmp/*.{png,jpg}', GLOB_BRACE);
See manual for glob.
Related
I need to get only the folder names in a directory. So far I found the DirectoryIterator to be useful. However I am not getting the desired names of the folders.
$dir = new DirectoryIterator(dirname($directory));
foreach ($dir as $fileinfo) {
if (!$fileinfo->isDot()) {
var_dump($fileinfo->getFilename());
if ($fileinfo->isDir()) {
//echo $fileinfo->getFilename() . '<br>';
}
}
}
Please see: I also want to skip the dots (.) and (..)
while having the ability to ignore folders I choose.
DirectoryIterator let you obtain filenames relatives to the directory not absolute, neither relative to the current directory of your process. Concatenate $directory and $fileinfo->getFileName() to obtain a correct usable path.
Here is a solution:
$path = 'PATH';
if ($handle = opendir($path)) {
while (false !== ($file = readdir($handle))) {
//skips dots
if ('.' === $file) continue;
if ('..' === $file) continue;
//ignore folders
if ('FOLDER_TO_IGNORE' === $file) continue;
//check if filename is a folder
if (is_dir($file)){
//DO SOMETHING WITH FOLDER ($file)
}
}
closedir($handle);
}
I am trying for the life of me to find the best way to delete all files in a single directory excluding a single file extension, ie anything that is not .zip
The current method I have used so far which successfully deletes all files is:
$files = glob('./output/*');
foreach($files as $file)
{
if(is_file($file))
unlink($file); // delete file
}
I have tried modifying this like so:
$files = glob('./output/**.{!zip}', GLOB_BRACE);
foreach($files as $file)
{
if(is_file($file))
unlink($file); // delete file
}
However, I am not hitting the desired result. I have changed the line as follows which has deleted only the zip file itself (so I can do the opposite of desired).
$files = glob('./output/*.{zip}', GLOB_BRACE);
I understand that there are other methods to read directory contents and use strpos/preg_match etc to delete accordingly. I have also seen many other methods, but these seem to be quite long winded or intended for recursive directory loops.
I am certainly not married to glob(), I would simply like to know the simplest/most efficient way to delete all files in a single directory that are not a .zip file.
Any help/advice is appreciated.
$exclude = array("zip");
$files = glob("output/*");
foreach($files as $file) {
$extension = pathinfo($file, PATHINFO_EXTENSION);
if(!in_array($extension, $exclude)) unlink($file);
}
This code works by having an array of excluded extensions, it loads up all files in a directory then checks for the extension of each file. If the extension is in the exclusion list then it doesn't get deleted. Else, it does.
This should work for you:
(I just use array_diff() to get all files which are different to *.zip and then i go through these files and unlink them)
<?php
$files = array_diff(glob("*.*"), glob("*.zip"));
foreach($files as $file) {
if(is_file($file))
unlink($file); // delete file
}
?>
How about calling to the shell? So in Linux:
$path = '/path/to/dir/';
$shell_command = escapeshellcmd('find ' . $path .' ! -name "*.zip" -exec rm -r {}');
$output = shell_exec($shell_command);
I would simply like to know the simplest/most efficient way to delete all files in a single directory that are not a .zip file.
SPL Iterators are very effective and efficient.
This is what I would use:
$folder = __DIR__;
$it = new FilesystemIterator($folder, FilesystemIterator::SKIP_DOTS);
foreach ($it as $file) {
if ($file->getExtension() !== 'zip') {
unlink($file->getFilename());
}
}
Have you tried this:
$path = "dir/";
$dir = dir($path);
while ($file = $dir->read()) {
if ($file != "." && $file != ".." && substr($file, -4) !== '.zip') {
unlink($file);
}
}
I try to make a gallery. In a folder I have some duplicate pictures. I have pictures named: af_160112, af_160113, af_160114. I would like remove this first one. How to take the first picture in a folder and delete it? So far I have known that I should use unlinke($file) function. Thank you for your help.
Solved.
I used:
$files = glob($path_to_gallery . '/*.{jpg,png,gif}', GLOB_BRACE);
foreach($files as $file) {
unlink($file);
break;
}
$path = 'full_path/gallery/';
$dir = opendir($path);
while ($dir && ($file = readdir($dir)) !== false) {
unlink($path.$file);
break;
}
I am trying to read a file name current.conf and then use the name of a folder saved in it to opendir(); when I open:
$file = fopen("current.conf","r");
$lines = fread($file,"10");
fclose($file);
$lines = "/".$lines."/";
echo $lines;
$dir=opendir($lines);
$files=array();
while (($file=readdir($dir)) !== false)
{
if ($file != "." and $file != ".." and $file != "index.php")
{
array_push($files, $file);
}
}
closedir($dir);
The current.conf has only one line in it:
2.1-2328
I am not able to open the folder that is named in the conf files. I have a feeling it has to do with the formatting of the conf file but not sure.
I suspect the directory doesn't exist (or you don't have the rights to read it), but without a specific error (opendir is most likely throwing an E_WARNING - check your logs, etc.)
Incidentally, you could re-write your code to reduce its complexity as follows:
<?php
// Grab the contents of the "current.conf" file, removing any linebreaks.
$dirPath = '/'.trim(file_get_contents('current.conf')).'/';
$fileList = scandir($dirPath);
if(is_array($fileList)) {
foreach($fileList as $file) {
// Skip the '.' and '..' in here as required.
echo $file."\n";
}
}
else echo $dirPath.' cound not be scanned.';
?>
In this instance the call to scandir will throw an E_WARNING.
I am trying to make a function that scans a folder for subfolders and then returns
a numeric array with the names of those folders.
This is the code i use for testing. Once i get it to print out the folder names and not just "." and ".." for present and above folder all will be well, and I can finish the function.
<?php
function super_l_getthemes($dir="themes")
{
if ($handle = opendir($dir)) {
echo "Handle: {$handle}\n";
echo "Files:\n";
while (false !== ($file = readdir($handle))) {
echo "{$file}<br>";
}
closedir($handle);
}
?>
The above code works fine, and prints out all the contents of the folder: files, subfolders and the "." and ".."
but if i replace:
while (false !== ($file = readdir($handle))) {
echo "{$file}<br>";
}
with:
while (false !== ($file = readdir($handle))) {
if(file_exists($file) && is_dir($file)){echo "{$file}";}
}
The function only prints "." and ".." , not the two folder names that I'd like it to print.
Any help is appreciated.
You must provide the absolute path to file_exists, otherwise it will look for it in the current execution path.
while (false !== ($file = readdir($handle))) {
$file_path = $dir . DIRECTORY_SEPARATOR . $file;
if (file_exists($file_path) && is_dir($file_path)) {
echo "{$file}";
}
}
The problem with readdir is that it only reads the strings of the named entries inside of the directory.
For instance, if you had file "foo" inside of directory "/path/to/files/", when using readdir on "/path/to/files/", you would eventually come to the string "foo".
Normally this wouldn't be a problem if it were in the same directory as the current working directory of the script, but, since you are reading from an arbitrary director, when you are attempting to inspect the entry (file, directory, whatever), you are calling is_dir on the bare string "foo".
I would try prefixing the name you pull out using readdir with the path to the file.
if ($handle = opendir($dir)) {
echo "Handle: {$handle}\n";
echo "Files:\n";
while ($file = readdir($handle)) {
/*** make $file into an absolute path ***/
$absolute_path = $dir . '/' . $file;
/*** NOW try stat'ing it ***/
if (is_dir($absolute_path)) {
/* it's a directory; do stuff */
}
}
closedir($handle);
}
You need to use:
while (false !== ($file = readdir($handle))) {
if(file_exists($dir.'/'.$file) && is_dir($dir.'/'.$file)){echo "{$file}";}
}
See http://php.net/readdir
If you only want the directories of the starting folder, you can simply do:
glob('/some/path/to/search/in/*', GLOB_ONLYDIR);
which would given you only those foldernames in an array. If you want all directories below a given path, try SPL's RecursiveDirectoryIterator
$fileSystemIterator = new RecursiveIteratorIterator(
new RecursiveDirectoryIterator('/some/path/to/look/in'),
RecursiveIteratorIterator::SELF_FIRST);
Iterators can be used with foreach:
$directories = array();
foreach($fileSystemIterator as $path => $fileSystemObject) {
if($fileSystemObject->isDir()) {
$directories[] = $path;
}
}
You will then have an array $directories with all directories under the given path.
$files = array();
foreach(new DirectoryIteraror('/path') as $file){
if($file->isDir() /* && !$file->isDot()*/) $files[] = $file->getFilename();
}
[edit: though you wanted to skip the dot, commented it out)
I don't think you need both file_exists and is_dir,
You just need the is_dir function. From the manual:
is_dir Returns TRUE if the filename exists and is a directory, FALSE otherwise.
Use this:
while (false !== ($file = readdir($handle))) {
if(is_dir($file)){echo "{$file}";}
}
is_dir will also check whether it's a relative path or an absolute path.
$directory = scandir($path);
foreach($directory as $a){
if(is_dir($path.$a.'/') && $a != '.' && $a != '..'){
echo $a.'<br/>';
}
}
With the path given as shown, it displays the folders present in the path.
I agree with nuqqsa's solution, however, I'd like to add something to it.
Instead of specifying the path, you can change the current directory instead.
For example,
// open directory handle
// ....
chdir($dir);
while (false !== ($file = readdir($handle)))
if(is_dir($file))
echo $file;
// close directory handle