I am trying to rename the files contained in 2 or more directories. Maybe this question was asked before but I'm stuck on this problem. Any help is greatly appreciated
main directory:
sub folder where files located:
resources/country/England/ (fileshere)
$dir = scandir($_SERVER['DOCUMENT_ROOT']."/resources/country"); if(!empty($dir) && is_array($dir)){ foreach($dir as $d){ $sub_dir = scandir($_SERVER['DOCUMENT_ROOT']."/resources/country/".$d); if(!empty($sub_dir)){ foreach($sub_dir as $s_dir){ if($s_dir != '..' && $s_dir != '.'){ $mynew_dir = $_SERVER['DOCUMENT_ROOT']."/resources/country/".utf8_decode($d)."/"; if ($handle = opendir($mynew_dir)) { while (false !== ($fileName = readdir($handle))) { //$newName = str_replace("SKU#","",$fileName); if(is_file($fileName)){ $newName = urlencode($fileName); if(rename($fileName, $newName)){ print"<div>Rename Successful: Filename:".$fileName." Newname: ".$newName."</div>"; }else{ print"<div>Rename UnSuccessful: Filename:".$fileName." Newname: ".$newName."</div>"; } } } closedir($handle); }else{ print print"<div>Rename UnSuccessful: Failed to open: " .$d."</div>"; } } } }else{ print"<div>Rename UnSuccessful: Empty</div>"; } } }
is_file() will treat '.' and '..' as files and will allow them in the path. rename() needs absolute path
<?php
$dir = scandir($_SERVER['DOCUMENT_ROOT']."/resources/country");
if(!empty($dir) && is_array($dir))
{
foreach($dir as $d)
{
if(strcasecmp($d, '..')!=0 && strcasecmp($d, '.')!=0) //You need to check the first two files in the base directory as well. Else you will always go one directory back if the path contains '. or '..'
{
$sub_dir = scandir($_SERVER['DOCUMENT_ROOT']."/resources/country/".$d);
if(!empty($sub_dir))
{
foreach($sub_dir as $s_dir)
{
if(strcasecmp($s_dir, '..')!=0 && strcasecmp($s_dir, '.')!=0)
{
$mynew_dir = $_SERVER['DOCUMENT_ROOT']."/resources/country/".$d; // No need to use another '/'
if ($handle = opendir($mynew_dir))
{
while (false !== ($fileName = readdir($handle)))
{
//$newName = str_replace("SKU#","",$fileName);
if(strcasecmp($fileName, '..')!=0 && strcasecmp($fileName, '.')!=0) //is_file treats '.' and '..' as files which you want to avoid
{
$newName = urlencode($fileName);
if(rename($mynew_dir."/".$fileName, $mynew_dir."/".$newName)) //rename() needs an absoulute path
{
print"<div>Rename Successful: Filename:".$fileName." Newname: ".$newName."</div>";
}else{
print"<div>Rename UnSuccessful: Filename:".$fileName." Newname: ".$newName."</div>";
}
}
}
closedir($handle);
}else{
print print"<div>Rename UnSuccessful: Failed to open: " .$d."</div>";
}
}
}
}else{
print"<div>Rename UnSuccessful: Empty</div>";
}
}
}
}
?>
I assume that the resource/ folder and this php script are in root directory. If you want to place them inside another folder, add the folder name everywhere in $_SERVER['DOCUMENT_ROOT']."/resources/country/"
Original code had a main problem - directory traversial. The base directory $_SERVER['DOCUMENT_ROOT']."/resources/country"
was read multiple times.
When the renaming itself occured, there were no checks if the $fileName
is aclually a file - it was possible to rename directories as well.
Also there were several absolutely un-necessary error messages, which i removed.
The first answer was partly correct, rename()
does need an absolute path. However is_file
works perfectly fine when you supply it an absolute path.
Assuming folder structure /resourses/country/...
is placed in the servers document root folder(can be anything, not necessarly php root folder. Depends greatly on setups) the code for working exapmle will look like:
<?php
$dir = scandir($_SERVER['DOCUMENT_ROOT']."/resources/country");
if(!empty($dir) && is_array($dir)) {
foreach($dir as $d) {
/* $dir will always include '.' and '..' as the first two elemets of the array.
* The check below ensures, that you exclude these elements from further traversial.
* If you don't make this check, you will also read the parent of your directory and the directory itself
*/
if($d != '.' && $d != '..') {
/*
* Here, we ensure ourselves that we actually selected a directory and not a file.
*/
if(is_dir($_SERVER['DOCUMENT_ROOT']."/resources/country/".utf8_decode($d)))
{
$sub_dir = $_SERVER['DOCUMENT_ROOT']."/resources/country/".utf8_decode($d)."/";
/*
* Here, no extra checks are needed, we already ensured ourselves that we selected the correct directory.
* We just need to open it and read it's contents.
*/
if ($handle = opendir($sub_dir)) {
while (false !== ($fileName = readdir($handle))) {
/*
* Here is_file() actually take care of all the necessary checks.
* When absolute path is supplied, it will only return true for actual files.
* '.' and '..' will be treated as non-files. Any subfolders will be also ignored.
*/
if(is_file($sub_dir."/".$fileName))
{
/* Here we make file name modifications. It can be any modifications.
* As an axample I added appending 'new_' to file name.
* Also for the sake of not forgetiing we encode the new file name strate away;
*/
$new_fileName = "new_" . $fileName;
$encoded_name = urlencode($new_fileName);
/*
* Here we do the renaming itself.
* As it was said earlier 'rename()' needs an absolute path to work correctly
*/
if(rename($sub_dir."/".$fileName, $sub_dir."/".$new_fileName)) {
print"<div>Rename Successful: Filename: ".$fileName." Newname: ".$new_fileName."</div>";
} else {
print"<div>Rename UnSuccessful: Filename: ".$fileName." Newname: ".$new_fileName."</div>";
}
}
}
closedir($handle);
}
}
}
}
}
I left the comments inside the code, to explain a little better what the code does and why it does it.
The above example was tested on Windows, and works there. Linux can have problems with this, as far as I know folder must have attribute x
(executable) set, for this code to work.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.