How to delete all files except one from a directory using PHP?
Asked Answered
B

5

9

I have a few directories with some files in them:

/test1/123.jpg
/test1/124.jpg
/test1/125.jpg
/test2/123.jpg
/test2/124.jpg

I want to delete all except for /test1/124.jpg or /test2/124.jpg?

I know the directory name and the file name. Is there a way of doing that in a Linux environment with php and maybe unlink?

Bille answered 10/8, 2012 at 23:27 Comment(0)
T
1

8 years ago I wrote this quick hack that got accepted but please take on account that

  • It is platform dependent: It will work on unix-like systems only, as it depends on unix-like paths and rm and mv delete and move shell commands.
  • It requires php config to allow running system shell commands via shell_exec (Something I would not recommend unless you know what you are doing)
  • It is quite an ad-hoc answer to the proposed question, not even fancy enough to use a foreach iteration on an array of file names, which allows for a much more general solution.
  • It does not perform error capture of any kind so your script will silently continue on failure (Also capturing errors on shell_exec is not trivial since you do not get the exit code as you can do with alternatives like exec or system)

However it has the advantage of running all deletions in a single shell command and it does not require an extra exclusion lookup per processed file, which makes it run quite fast on high deletion vs. preserving ratios, if performance is what you are looking for:

    for ($i=1;$i<=2;$i++){
        shell_exec ('mv /test'.$i.'/124.jpg /test'.$i.'/keep.jpg');
        shell_exec ('rm /test'.$i.'/12*.jpg');
        shell_exec ('mv /test'.$i.'/keep.jpg /test'.$i.'/124.jpg');
    }

Anyway if you look right here a few other answers that propose an unlink based solution were added after mine, which (as discussed in the comments below) is a much better approach, to which I'd also suggest

  • Adding error handling, as unlink might fail to delete an existing file on permission issues when the file is in use or the script execution user is not allowed to modify it.

  • Always ini_get('max_execution_time'); to check your script execution timeout settings (and consider using set_time_limit to extend it for your script if necessary) before running a script processing an unknowingly long list of files.

Topple answered 10/8, 2012 at 23:31 Comment(4)
Dirty hack. You shouldn't use that example if you can write only PHP code. Only if you understand what and WHY you are doing.Pictogram
@Pictogram could you please enlight me with a better answer? I accept any kind of constructive criticism.Topple
@elcodedocle, there are two examples in the answers below. From HappyTimeGopher and from Counstantin-Loukas. They are using only PHP, so you don't have to know on which platform you code is executed as well as know if the shell_exec is allowed function on your hosting/server. It could be disabled because of security reasons. Again, if you understand WHY you are doing that you can. For example, performance issue.Pictogram
@Pictogram Ok, now I see what you mean. I will use and recommend unlink and language specific calls from now on, unless performance is an issue. Thank you :)Topple
A
37

Just edit $dir and $leave_files to edit the locations and files.

$dir = 'test1';
$leave_files = array('124.jpg', '123.png');

foreach( glob("$dir/*") as $file ) {
    if( !in_array(basename($file), $leave_files) ){
        unlink($file);
    }
}

You'd run that once for each directory.

Also remember to make $dir a full path (with no trailing slash) if the target directory isn't in the same folder as this script.

Aldose answered 10/8, 2012 at 23:34 Comment(2)
how to do it for the root directory serving the domain? like for the public_html directory on the server and the project folder on localhost?Xuanxunit
@Xuanxunit just change the $dir var to the path of whatever you want.Aldose
S
4

Perhaps a little crude, but if you're on a Linux system you could do this (assuming you're in the correct directory):

<?php shell_exec('rm $(ls * | grep -v '.$fileYouWantToKeep.')'); ?>

You will obviously need to filter that variable if contains any user input though.

Snowwhite answered 10/8, 2012 at 23:33 Comment(0)
T
1

8 years ago I wrote this quick hack that got accepted but please take on account that

  • It is platform dependent: It will work on unix-like systems only, as it depends on unix-like paths and rm and mv delete and move shell commands.
  • It requires php config to allow running system shell commands via shell_exec (Something I would not recommend unless you know what you are doing)
  • It is quite an ad-hoc answer to the proposed question, not even fancy enough to use a foreach iteration on an array of file names, which allows for a much more general solution.
  • It does not perform error capture of any kind so your script will silently continue on failure (Also capturing errors on shell_exec is not trivial since you do not get the exit code as you can do with alternatives like exec or system)

However it has the advantage of running all deletions in a single shell command and it does not require an extra exclusion lookup per processed file, which makes it run quite fast on high deletion vs. preserving ratios, if performance is what you are looking for:

    for ($i=1;$i<=2;$i++){
        shell_exec ('mv /test'.$i.'/124.jpg /test'.$i.'/keep.jpg');
        shell_exec ('rm /test'.$i.'/12*.jpg');
        shell_exec ('mv /test'.$i.'/keep.jpg /test'.$i.'/124.jpg');
    }

Anyway if you look right here a few other answers that propose an unlink based solution were added after mine, which (as discussed in the comments below) is a much better approach, to which I'd also suggest

  • Adding error handling, as unlink might fail to delete an existing file on permission issues when the file is in use or the script execution user is not allowed to modify it.

  • Always ini_get('max_execution_time'); to check your script execution timeout settings (and consider using set_time_limit to extend it for your script if necessary) before running a script processing an unknowingly long list of files.

Topple answered 10/8, 2012 at 23:31 Comment(4)
Dirty hack. You shouldn't use that example if you can write only PHP code. Only if you understand what and WHY you are doing.Pictogram
@Pictogram could you please enlight me with a better answer? I accept any kind of constructive criticism.Topple
@elcodedocle, there are two examples in the answers below. From HappyTimeGopher and from Counstantin-Loukas. They are using only PHP, so you don't have to know on which platform you code is executed as well as know if the shell_exec is allowed function on your hosting/server. It could be disabled because of security reasons. Again, if you understand WHY you are doing that you can. For example, performance issue.Pictogram
@Pictogram Ok, now I see what you mean. I will use and recommend unlink and language specific calls from now on, unless performance is an issue. Thank you :)Topple
J
1

Here's another option:

<?php
$dirList = array('/path/to/dir1','/path/to/dir2'); //List of Dirs with files to be deleted. No trailing slash
$saved = array('path/to/file1','path/to/file2'); //List of files to be saved, no leading slash

foreach($dirList as $directory){
$list = scandir($directory);
foreach($list as $file){
if(!is_int(array_seach($directory.'/'.$file,$saved))){ //Array search returns key if needle exists, so we check if it does not return int
unlink($file);
}
}
}

?>

I don't have access to my server right now so I haven't tested it but I think it should work. Try it on some test directories first and see if it works.

Jankell answered 10/8, 2012 at 23:42 Comment(0)
F
0

you could move the files to a temp folder, then erase the folder, make a new fand move the folder with the name of the old one, and move the fotos back, erase tmp folder. $ profit $

Feldspar answered 5/1, 2013 at 5:49 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.