View Full Version : Remove unused images using php

09-07-2009, 06:19 AM
41,000 images, 18,000 are needed. I have an xls spreadsheet of images not needed and need to remove them but keep the 18,000 (also in spreadsheet).

Any suggestions how to separate? Found this php file but it times out on server, works if I hand select 100 or so, but need one-time fix.

remove__unused_images.php v1.1b by pyramids 11-6-2008

What this script does:
* Read the database and report back a list of installed images
* Mark (in RED) any DB listed image which does not exist on the server
* Read the server images and report back a list
* Compare the lists for missing data
* Offer you the ability to check or uncheck listed images controlling what gets renamed
* Rename the USER checked listed images from myimage.jpg to #UNUSED_myimage.jpg
* Allow you to ftp and delete ALL renamed #UNUSED_myimage.jpg images

Design note:
I decided not to let the script delete the images for safety purposes, but the script can be altered easily to do so, edit this line - if (rename($root_images_dir . '/' . $checked_un.........
It only looks for jpg images, to alter search for and edit the lines holding 'jpg'

The script will NOT:
* Delete any files
* Write to the database
* Write any files

The script will not report the correct results if you are looking in the wrong folder or reading the wrong table in the database. So if you are getting funny results, then check your settings.

This script when run will first present to the user the image info, allowing the user to check or uncheck the images to be renamed.

The default setting is for one table called products and a column called products_image
The default folder is called images
If your setup is modified you will need to edit the settings in more detail below.

The script will also list images that may be installed in the shop but not listed in the image folders.

* Installation instructions:
* Install in the Admin root and run (mydomain.com/admin/remove_unused_images.php)

AZER **********

added back some bacgrounf on columns background bgcolor="#F5F5F5"
commented gif reports since it give a lot of infos on image type few people use for products photos
changed server variable to get them from configure.php variable
to do : folow the osc php file layout and call the js + html code on the proper section




// azer modifid to read from configure.php : $root_dir = 'v:/easyphp/www/ms2fr/shop'; // look in this root
$root_dir = DIR_FS_CATALOG ; // look in this root

// azer modifid to read from configure.php : $base_dir = 'http://localhost/ms2fr/shop'; // for links
$base_dir = HTTP_SERVER . DIR_WS_CATALOG ; // for links

// if script timesout you may elect to turn off the displays for the list of images
// in the DB and the server, this will free up server resources,
// the lists are for infomational purposes only anyway.

$turn_off_db_display = 1; // 0 means it is on, 1 means it is off

$turn_off_server_display = 1; // 0 means it is on, 1 means it is off

// look in this images folder - do not add more folders here - just the main one
$images_dir = 'the-web-images';

// if you add more sub folders of $images_dir then edit as EX: $more_folders = array("thumb","full");
// you must make sure the corresponding tables are in $table_array
$more_folders = array();

// to add more tables use ex: $table_array = array("products_image");
// see below for possible image names
// $table_array = array("products_image");
$table_array = array("products_image");
/* Additional possible image names

,"products_image_med","products_image_lrg","products_image_sm_1","products_image_xl_1","products_image_sm_2","products_image_xl_2","products_image_sm_3","products_image_xl_3","products_image_sm_4","products_image_xl_4","products_image_sm_5", "products_image_xl_5","products_image_sm_6","products_image_xl_6"


// name of this script
$script_name = "remove_unused_images.php";

/* ADVANCED OPTION for SQL query -

DEFAULT SETTING: get all products even if status is off and there is no quantity
$optional_sql = ""

get image info if the product status is on or if the product has a qty greater than 0 example query:
$optional_sql = " where p.products_status = '1' or p.products_quantity >= '0'";

get image info if the product status is on only example query:
$optional_sql = " where p.products_status = '1'";
$optional_sql = " where p.products_status = '1'";
// Do not edit below //

<script type="text/javascript"><!--
var formblock;
var forminputs;
function prepare() {
formblock= document.getElementById("form_id");
forminputs = formblock.getElementsByTagName("input");
function select_all(name, value) {
for (i = 0; i < forminputs.length; i++) {
// regex here to check name attribute
var regex = new RegExp(name, "i");
if (regex.test(forminputs[i].getAttribute("name"))) {
if (value == "1") {
forminputs[i].checked = true;
} else {
forminputs[i].checked = false;
if (window.addEventListener) {
window.addEventListener("load", prepare, false);
} else if (window.attachEvent) {
window.attachEvent("onload", prepare)
} else if (document.getElementById) {
window.onload = prepare;


// AZERISH *****
//original: AZER removed the extra slash : $root_images_dir = $root_dir . '/' . $images_dir;// look in this main images folder

$root_images_dir = $root_dir . $images_dir;// look in this main images folder

if (!file_exists($root_images_dir)) {echo "<font size=2>Can't find the <b>".$root_images_dir."</b> file. <b>NOTE: </b>This script needs to run in the shop folder</font>";die();}

// Read the database, then put all existing db images into an array called $full_image_list[]
$sql = "select";

$numb_tables = count($table_array);
if ($numb_tables)
for ($i = 0; $i < $numb_tables; ++$i)
if($i == ($numb_tables-1))
$sql .= ' p.' . $table_array[$i] . ' ';
$sql .= ' p.' . $table_array[$i] . ', ';

$sql .= "from products p";

$sql .= $optional_sql;

if (require ('includes/configure.php')){}else{echo '<b>ERROR - could not locate the config file</b><br><br>';break;}// login info

$conn = mysql_connect(DB_SERVER, DB_SERVER_USERNAME, DB_SERVER_PASSWORD) or die("<b>ERROR - could not connect to the database</b><br><br>" . mysql_error());// connect to db

$select_db = mysql_select_db(DB_DATABASE, $conn) or die("<b>ERROR - could not select the database</b><br><br>" . mysql_error());//select the right db

$image_info_query = mysql_query($sql, $conn) or die("<b>ERROR - could not query the database</b><br><br>" . mysql_error());

// put the images in an array
while ($image_info = mysql_fetch_array($image_info_query))
if ($numb_tables)
for ($i = 0; $i < $numb_tables; ++$i)
// ***azerish if( strpos($image_info[$table_array[$i]], 'jpg') || strpos($image_info[$table_array[$i]], 'gif') || strpos($image_info[$table_array[$i]], 'png') )
if (strpos($image_info[$table_array[$i]], 'jpg') )

if($image_info[$table_array[$i]]){$full_image_list[] = strip_tags($image_info[$table_array[$i]]);}//put all db images into 1 array

$full_image_list = array_unique($full_image_list);
sort($full_image_list);// list from db

$count_db_list = count($full_image_list);//number of images installed in the database

// end reading the database for installed images

// get the server images/
$files = array();

$numb_folders = count($more_folders);

if ($numb_folders)
for ($i = 0; $i < $numb_folders; ++$i)

$files = array_unique($files);
sort($files);// server file list
$count_server_list = count($files);//number of files on the server

// start the html listing page

<!doctype html public "-//W3C//DTD HTML 4.01 Transitional//EN">
<html <?php echo HTML_PARAMS; ?>>
<meta http-equiv="Content-Type" content="text/html; charset=<?php echo CHARSET;?>">
<title><?php echo TITLE; ?></title>
<link rel="stylesheet" type="text/css" href="includes/stylesheet.css">
<body marginwidth="0" marginheight="0" topmargin="0" bottommargin="0" leftmargin="0" rightmargin="0" bgcolor="#FFFFFF">
<!-- header //-->
<?php require(DIR_WS_INCLUDES . 'header.php'); ?>
<!-- header_eof //-->

<!-- body //-->
<table border="0" width="100%" cellspacing="0" cellpadding="0">
<td width="<?php echo BOX_WIDTH; ?>" valign="top" id="left"><table border="0" width="<?php echo BOX_WIDTH; ?>" cellspacing="0" cellpadding="0">
<!-- left_navigation //-->
<?php require(DIR_WS_INCLUDES . 'column_left.php'); ?>
<!-- left_navigation_eof //-->
<td class="main"><table width="100%" border="0" align="center" cellpadding="0" cellspacing="0">
<td class="pageHeading">Rename Images that are not being called from the Database<br><br></td>
</table><table width="100%" border="0" align="center" cellpadding="2" cellspacing="2">
<!-- body_text //-->

//**** AZERISH ajout d'un background bgcolor="#F5F5F5"
$msg = '<td bgcolor="#EAF5F5" width="33%" valign="top"><font size="2">';

$msg .= '<b>*********************</b><br>
<b>List of DATABASE images stored</b><br>
<b>for the shop</b><br>
<b>The total number of images in the db are ' . $count_db_list . '</b><br>
<br>The database is being read as ' . $sql . '<br><br>';

for ($i = 0; $i < $count_db_list; ++$i)
if ($turn_off_db_display == 0)
if (file_exists($root_images_dir.'/'.$full_image_list[$i]))
$msg .= $full_image_list[$i] . "<br>";// print server images
$hold_red = 1;
$msg .= '<font color="Red" size="2">'.$full_image_list[$i] . '</font><br>';// print server images that are not in the server


if ($turn_off_db_display == 1){
$msg .= 'This list display of images is turned off, to turn on set $turn_off_db_display to 0<br>';

$msg .= '<br>';

/************** COVERT NEW FILES TO NORMAL FILENAME ****************/
//**** AZERISH ajout d'un background bgcolor="#F5F5F5"
$msg .= '</td><td bgcolor="#F5F5F5" width="33%" valign="top">
<font size="2" color="green">*********************</b><br>
<b>List of SERVER images</b><br>
<b>The total number of images on the server are ' . $count_server_list . "</b><br><br>";

$msg .= 'The following folders are being read:<br>' . $root_images_dir . '<br>';

if ($numb_folders)
for ($i = 0; $i < $numb_folders; ++$i)
$msg .= $root_images_dir.'/'.$more_folders[$i]. '<br>';

$msg .= '<br>';

for ($i = 0; $i < $count_server_list; ++$i)
$files[$i] = str_replace($root_images_dir . '/', "", $files[$i]);// remove the root part of the image name

if ($turn_off_server_display == 0)
$msg .= $files[$i] . "<br>";// echo server images

if ($turn_off_server_display == 1){
$msg .= 'This list display of images is turned off, to turn on set $turn_off_server_display to 0<br>';

$msg .= '</font>';

$image_diff = array_diff($files, $full_image_list);//return the images that are on the server and not in the db
$count_diff_list = count($image_diff);//the number of missing files

//**** AZERISH ajout d'un background bgcolor="#F5F5F5"
$msg .= '</td><td bgcolor="#B4F4F4" width="33%" valign="top">';

if ($HTTP_POST_VARS['action'] == 'rename') {}else{
$msg .= '<form id="form_id" name="unused_images" action="'.$script_name.'" method="post">';}

$msg .= '<font size="2" color="blue">*********************</b><br>
<b>List of UNUSED images, they were not found in the database</b><br>
<b>The total number of REPORTED unused images is ' . $count_diff_list . '</b><br><br>';

$hold_exist = ($count_server_list-$count_db_list);

if ($hold_exist < $count_diff_list ){
$msg .= '<b>It appears that you have </font><font size="2" color=red>'. ($count_diff_list-$hold_exist) .' (they are listed in red in the DB list, if list is displayed)</font><font color="blue" size="2"> images listed in the database that do not exist on the server</b><br><div align="center"><a href="remove_unused_images.php#end">List End - Click Here</a></div><br><br><br>';

if ($count_diff_list > 0)
for ($i = 0; $i < $count_diff_list; ++$i)
$msg .= '<a target="_blank" href="'.$images_dir.$image_diff[$i].'">'.$image_diff[$i].'</a> <input type="checkbox" name="checked_unused_images[]" value="'.$image_diff[$i].'"><br>';//unused images to rename checked

$msg .= '</font>';

$msg .= "<a name=button></a><a name=end></a><br><div align=center><a href=\"remove_unused_images.php#button\" onClick=\"select_all('checked_unused_images', '1');\"><font size=2><b>Check All Boxes</b></font></a><font size=2> | </font><a href=\"remove_unused_images.php#button\" onClick=\"select_all('checked_unused_images', '0');\"><font size=2><b>Uncheck All Boxes</b></font>

//start section where we process the images to rename
if ($HTTP_POST_VARS['action'] == 'rename') {

$msg_s = '<!doctype html public "-//W3C//DTD HTML 4.01 Transitional//EN"><html>
<head><title>Rename Unused Images</title></head><body><!-- body_text //--><table bgcolor="Lime" width="100%" border="0" align="center" cellpadding="0" cellspacing="0"><tr><td align="center"><h2>Rename Images that are not being called from the Database</h2></td></tr></table><br><table width="80%" border="0" align="center" cellpadding="0" cellspacing="0"><tr><td valign="top"><b><font size=2>The images listed below were renamed</font></b><br><br>';

$hold_change = 0;

//missing code line 318
$checked_unused_images = $HTTP_POST_VARS['checked_unused_images'];

if ($count_diff_list > 0)
for ($i = 0; $i < $count_diff_list; ++$i)

if ($checked_unused_images[$i])
$hold_change =1;
$rename_image_diff = '#UNUSED_' . $checked_unused_images[$i];

//if image is in a folder add the prefix
if (strpos($checked_unused_images[$i], '/')){
$rename_image_diff = str_replace('/', "/#UNUSED_", $checked_unused_images[$i]);//inserting the prefix after the /
}else{$rename_image_diff = '#UNUSED_' . $checked_unused_images[$i];}

if (rename($root_images_dir . '/' . $checked_unused_images[$i], $root_images_dir . '/' . $rename_image_diff)){
$msg_s .= '<font color="Blue">RENAMED </font>' . $root_images_dir . '/' . $checked_unused_images[$i] . '<font color="Blue"> TO </font>' . $root_images_dir . '/' . $rename_image_diff . '<br>';
}else{$msg_s .= 'UNKNOWN ERROR - The file ' . $checked_unused_images[$i] . 'did not get renamed';}


if ($hold_change ==0){$msg_s .= '<br><br><font color="red" size="4"><b>No boxes were checked, so nothing was done</b></font>';}
$msg_s .= '<br><br><b><font size="4">You may now FTP to your site, find the renamed files with the prefix of #UNUSED_ and delete them.</font></b>';

$msg_s .= '<br><br><div align="center"><a href="remove_unused_images.php">
Click here to run the script again

echo $msg_s;


$msg .= '<br><table width="100%" cellpadding="0"><tr><td><div align="center">

<input type="submit" name="submit" value=" Click Here to Rename ALL Checked Images ">

<font color="Red"><b>** CHECKED IMAGES will be RENAMED **</b></font><br><font size="2">After clicking wait for the script response page</font></div>
<br><font size=2>** IMPORTANT **<br>The Images with Checked boxes will be renamed with the prefix of #UNUSED_. So uncheck any images you may be using on the site that may not be listed in the database, but are being used on your pages - otherwise they will be renamed and will not show up on your site.<br><br>It is a good idea to double check if theses images are not being used before you proceed. The images above are linked to the image, you may click on them here to review in a new opened window.<br><br></font>
</td></tr></table><input type="hidden" name="action" value="rename"></form><!-- body_text_eof //--></td></tr></table></body></html>';

echo $msg;

function GetImageListFromServer($dir,&$files)
while (false!=($file=readdir($dp)))
// ******** AZERISH enleve gifs if( strpos($file, 'jpg') || strpos($file, 'gif') || strpos($file, 'png') ){
if( strpos($file, 'jpg') ){
$locn = $dir.'/'.$file;
$str = sprintf("%s", $locn);
$files[] = $str;
closedir($dp);//close the folders


09-07-2009, 03:23 PM
You might have a look at the set_time_limit (http://php.net/set_time_limit) function and add it into the code manually.

09-07-2009, 06:14 PM
Changed Max_execution_time in /etc/php.ini to 240000
Changed Max_input_time in /etc/php.ini to 90000
restarted httpd

Still timed out went to blank screen.

Tried to put set_time_limit(0) in the above code itself (not 100% sure where to put it) and that did not work.

Any suggestions?

09-08-2009, 04:19 AM
Hopefully this is ethical in this forum, would paypal someone for fix to this right away - we need this for a big project. Thanks!:thumbsup: