I'm using PHP to batch rename some local photos. The script is in the same directory as the photos.
The photos are named like 872376237_Photo_1_001.jpg. The first set of numbers (before the first underscore) is different for each file, and that's what I want to remove.
The format for the new file name should be Photo_1_001.jpg. In the PHP I get the new file name by using $newfilename = substr($filename, strpos($filename, '_') + 1);. Echo'ing out $newfilename shows the correct new file name.
The problem is when I call rename($filename, $newfilename) the files are getting renamed to 1_001.jpg. The $newfilename variable definitely contains the correct new file name. If I use copy() instead of rename() it works as expected. I can't figure this out.
Here's the code:
$dir = new DirectoryIterator(dirname(__FILE__));
foreach ($dir as $fileinfo) {
if (!$fileinfo->isDot()) {
$filename = $fileinfo->getFilename();
if ($filename != basename(__FILE__)) { // skip this script
$newfilename = substr($filename, strpos($filename, '_') + 1);
rename($filename, $newfilename);
}
}
}
EDIT: DevZer0 explained why this is happening in the comments. I thought DirectoryIterator compiled a list of all the files before iterating, but it does not. It will continuously iterate as long as new files are created (or renamed).
There's probably a better way to do this, but this works:
$dir = new DirectoryIterator(dirname(__FILE__));
$filenames = [];
foreach ($dir as $fileinfo) {
if (!$fileinfo->isDot()) {
$filename = $fileinfo->getFilename();
if ($filename != basename(__FILE__)) {
$newfilename = substr($filename, strpos($filename, '_') + 1);
array_push($filenames, [$filename, $newfilename]);
}
}
}
foreach ($filenames as $file) {
rename($file[0], $file[1]);
}
Related
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.
I have 100.000+ files with name RMA_(NUMBER)(DATE)(TIME).jpg like RMA_12345_2015_10_12_17_00_35.jpg
How I can move this file like RMA_35200_*.jpg?
You can use command:
$ mv RMA_35200_*.jpg new_path
or use php for that, example:
<?php
$fromPath = __DIR__ . '/from';
$toPath = __DIR__ . '/to';
$files = glob("{$fromPath}/RMA_35200_*.jpg");
foreach ($files as $file) {
$fileName = basename($file);
rename($file, "{$toPath}/{$fileName}");
}
Use glob()to find those files and rename() to move them
function moveFiles($source, $target) {
// add missing "/" after target
if(substr($target,-1) != '/') $target .= '/';
$files = glob($source);
foreach($files as $file) {
$info = pathinfo($file);
$destination = $target . $info['filename'];
rename($file, $destination);
}
}
moveFiles('/where/my/files/are/RMA_35200_*.jpg', '/where/they/should/be/';
I'd have to agree with the other comments, "Use glob()to find those files and rename() to move them", etc.
But, there's one thing I would add, a preg_match for the file name. PERL regular expression matching the file name. I think that's what you may be missing from these answers.
foreach ($files as $file) {
if (preg_match('/RMA_[0-9\-_]+.jpg/i', $file) {
...more code here...
}
}
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);
}
Need to remove user requested string from file name. This below is my function.
$directory = $_SERVER['DOCUMENT_ROOT'].'/path/to/files/';
$strString = $objArray['frmName']; // Name to remove which comes from an array.
function doActionOnRemoveStringFromFileName($strString, $directory) {
if ($handle = opendir($directory)) {
while (false !== ($file = readdir($handle))) {
if ($file != "." && $file != "..") {
if(!strstr($file,$strString)) {
continue;
}
$newfilename = str_replace($strString,"",$file);
rename($directory . $file,$directory . $newfilename);
}
}
closedir($handle);
}
}
It works partially good. But the mistake what in this routine is, renaming action also takes on file's extensions. What i need is, Only to rename the file and it should not to be affect its file extensions. Any suggestions please. Thanks in advance :).
I have libraries written by myself that have some of those functions. Look:
//Returns the filename but ignores its extension
function getFileNameWithOutExtension($filename) {
$exploded = explode(".", $filename);
array_pop($exploded);
//Included a DOT as parameter in implode so, in case the
//filename contains DOT
return implode(".", $exploded);
}
//Returns the extension
function getFileExtension($file) {
$exploded = explode(".", $file);
$ext = end($exploded);
return $ext;
}
So you use
$replacedname = str_replace($strString,"", getFileNameWithOutExtension($file));
$newfilename = $replacedname.".".getFileExtension($file);
Check it working here:
http://codepad.org/CAKdCAA0
I have this code which is taking the name of files in a directory and then creating a link to those files. However, the text in the link has the file extension on the end. I want to remove this but at the same time keep the correct link to the file i.e. the HTML link needs the extension to remain on it - like this:
File
So here is my script:
$linkdir="documents/other";
$dir=opendir("documents/other");
$files=array();
while (($file=readdir($dir)) !== false)
{
if ($file != "." and $file != ".." and $file != "index.php")
{
array_push($files, $file);
}
}
natcasesort($files);
$files=array_reverse($files);
foreach ($files as $file)
print "<li><a href='/$linkdir/$file' rel='external'>$file</a></li>";
Here is the code I need to integrate to remove the file extension:
$name = substr($file, 0, strrpos($file, '.'));
Any help with this will be greatly appreciated.
Could you mean that you want this?
foreach ($files as $file){
$name = substr($file, 0, strrpos($file, '.'));
print "<li><a href='/$linkdir/$file' rel='external'>$name</a></li>";
}
I can't find any other question in your post :)
Using pathinfo() is a more robust solution, in case some files have name with more dots (like someclass.inc.php):
$parts = pathinfo($file);
$name = $parts['basename'];