Rename function not working as expected - php

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

How to delete file in PHP

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.

PHP move files with specific name

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...
}
}

Get only folder names in a directory, skipping dots and ignoring certain folders

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);
}

Remove string from filename for all files (image files) available in the directory without affecting its extensions

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

Removing file extension in PHP, whilst also creating a link

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'];

Categories