rename all files in folder with random name - php

I want to rename all files in a folder with random numbers or characters.
This my code:
$dir = opendir('2009111');
$i = 1;
// loop through all the files in the directory
while ( false !== ( $file = readdir($dir) ) ) {
// do the rename based on the current iteration
$newName = rand() . (pathinfo($file, PATHINFO_EXTENSION));
rename($file, $newName);
// increase for the next loop
$i++;
}
// close the directory handle
closedir($dir);
but I get this error:
Warning: rename(4 (2).jpg,8243.jpg): The system cannot find the file specified

You're looping through files in the directory 2009111/, but then you refer to them without the directory prefix in rename().
Something like this should work better (though see the warning about data loss below):
$oldName = '2009111/' . $file;
$newName = '2009111/' . rand() . (pathinfo($file, PATHINFO_EXTENSION));
rename($oldName, $newName);
Of course, you may want to put the directory name in a variable or make other similar tweaks. I'm still not clear on why you're trying to do this, and depending on your goals there may be better ways of reaching them.
Warning! The approach you are using could cause data loss! A $newName could be generated that is the same name as an existing file, and rename() overwrites target files.
You should probably make sure $newName doesn't exist before you rename().

Related

Get latest file in dir including subdirectory php

i found out that i can use
$files = scandir('c:\myfolder', SCANDIR_SORT_DESCENDING);
$newest_file = $files[0];
to get the latest file in the given directory ('myfolder').
is there an easy way to get the latest file including subdirectorys?
like:
myfolder> dir1 > file_older1.txt
myfolder> dir2 > dir3 > newest_file_in_maindir.txt
myfolder> dir4 > file_older2.txt
Thanks in advance
To the best of my knowledge, you have to recursively check every folder and file to get the last modified file. And you're current solution doesn't check the last modified file but sorts the files in descending order by name.
Meaning if you have a 10 years old file named z.txt it will probably end up on top.
I've cooked up a solution.
The function accepts a directory name and makes sure the directory
exists. It returns null when the directory has no files or any of its subdirectories.
Sets aside the variables $latest and $latestTime where the last modified file is stored.
It loops through the directory, avoiding the . and .. since they can cause an infinite recursion loop.
In the loop the full filename is assembled from the initial directory name and the part.
The filename is checked if it is a directory if so it calls the same function we are in and saves the result.
If the result is null we continue the loop otherwise we save the file as the new filename, which we now know is a file.
After that we check the last modified time using filemtime and see if the $latestTime is smaller meaning the file was modified earlier in time that the current one.
If the new file is indeed younger we save the new values to $latest and $latestTime where $latest is the filename.
When the loop finishes we return the result.
function find_last_modified_file(string $dir): ?string
{
if (!is_dir($dir)) throw new \ValueError('Expecting a valid directory!');
$latest = null;
$latestTime = 0;
foreach (scandir($dir) as $path) if (!in_array($path, ['.', '..'], true)) {
$filename = $dir . DIRECTORY_SEPARATOR . $path;
if (is_dir($filename)) {
$directoryLastModifiedFile = find_last_modified_file($filename);
if (null === $directoryLastModifiedFile) {
continue;
} else {
$filename = $directoryLastModifiedFile;
}
}
$lastModified = filemtime($filename);
if ($lastModified > $latestTime) {
$latestTime = $lastModified;
$latest = $filename;
}
}
return $latest;
}
echo find_last_modified_file(__DIR__);
In step 7 there is an edge case if both files were modified at the exact same time this is up to you how you want to solve. I've opted to leaving the initial file with that modified time instead of updating it.

PHP/Laravel file existence verification not working

I have a <form> with a multiple file input that stores those files into the server. The names of the files must follow a numeric standard and that's why I rename them before storing. Each post has an ID an can have more than one file so the pattern is: post-id + dash and a number + file extension, this way, if the same post has two file with the same extensions, the dash + number will avoid them to be overwriten. So, before I store the files I run a loop to find the proper number to the name. The problem is, the function to verify the existence of the file seems not to be returning true when it should. The code:
$counter = 0;
do{
$nomeArquivo = $post->id . "-{$counter}" . "." . $arq->extension();
$counter++;
//these commented are other ways of verification I tried
//}while(Storage::exists($nomeArquivo));
//}while(file_exists("/storage/" . $nomeArquivo));
}while(is_file("/storage/" . $post->id . "-{$counter}"));
Storage::putFileAs('/public', $arq, $nomeArquivo);
This code above runs inside a foreach($files as $arq) where $files are the files from the form input.
Reference: https://laravel.com/docs/5.4/filesystem and https://laravel.com/api/5.4/Illuminate/Filesystem/Filesystem.html
Use the File Facade to check for the existence of a file:
File::exists($myfile)
http://laravel-recipes.com/recipes/123/determining-if-a-file-exists
If name of the file need to be unique only then,
You can give Unique Name like this:
$file = $request->file('file');
$extension = $file->getClientOriginalExtension();
$destination ='/files/';
$filename = uniqid() . '.' . $extension;
$file->move($destination, $filename);
Now save above file name in your database. Hope it may help you
As user #fubar pointed in the comments, I was referencing the wrong path to verify the existence of the file. I change the while condition to while(\File::exists(public_path() . '/storage/' . $nomeArquivo)) and it worked well. Thanks

How do I rename a filename before uploading with php

I need to upload two files with different ext example :
file_1.txt and file_image.png
when the user sent the two files using upload an form :
file_1.txt and file_image.png
before move_uploaded_file I need to rename the image name to be like the txt. name file :
file_1.txt
file_1.jpeg
I just want to rename the image filename, not the extension
Code is something like this :
switch($_REQUEST['action']) {
case "upload":
$Imagefile_temp = $_FILES['file']['tmp_name'];
$Textfile_temp = $_FILES['file']['tmp_name'];
$Imagefile_name = $_FILES['file']['name'];
$Textfile_name = $_FILES['file']['name'];
$ImageFileType = array('png' ,'jpg');
$TextFileType = array('txt');
$Image_extension = pathinfo($Imagefile_name, PATHINFO_EXTENSION); // holds the file extension of the file
$Text_extension = pathinfo($Textfile_name, PATHINFO_EXTENSION); //holds the file extension of the file
// //Declaring Path for uploaded images
$file_path = "uploads";
//checks for duplicate files
if((!file_exists($file_path."/".$Imagefile_name)) || (!file_exists($file_path."/".$Textfile_name))) {
$j = 0; //Variable for indexing uploaded image
for ($i = 0; $i < count($_FILES['file']['name']); $i++) {//loop to get individual element from the array
if(in_array($Image_extension,$ImageFileType) ) {
$Image_extension = explode('.', basename($_FILES['file']['name'][$i]));//explode file name from dot(.)
$file_extension = end($Image_extension); //store extensions in the variable
$target_path = $target_path . md5(uniqid()) . "." . $Image_extension[count($Image_extension) - 1];//set the target path with a new name of image
$j = $j + 1;//increment the number of uploaded images according to the files in array
$Imagefilestatus = move_uploaded_file($Imagefile_temp,$file_path."/"."image_".$Imagefile_name) ;//if file moved to uploads folder
}
if(in_array($Text_extension,$TextFileType) ) {
$Text_extension = explode('.', basename($_FILES['file']['name'][$i]));//explode file name from dot(.)
$file_extension = end($Text_extension); //store extensions in the variable
$target_path = $target_path . md5(uniqid()) . "." . $Text_extension[count($Text_extension) - 1];//set the target path with a new name of image
$j = $j + 1;//increment the number of uploaded images according to the files in array
$Textfilestatus = move_uploaded_file($Textfile_temp,$file_path."/".$Textfile_name) ;//if file moved to uploads folder
}
}
}
}
$name = 'Whatevernameyouwant.'.pathinfo($_FILES['file']['name'], PATHINFO_EXTENSION);
pathinfo with parameter PATHINFO_EXTENSION returns the file extension.
You can just explode the text file from the extension and use it as the image file name when moving it :
$text_file_name = $_FILES["text"]["name"]; // give you the text file name
$image_file_name = $_FILES["image"]["name"]; // give you the image file name
$file_expensions = strtolower(end(explode(".", $image_file_name))); // give you the image extension and so you can use it later for saving the file
$n = explode(".", $text_file_name, 1);
$name = $n[0]; // get text file name
$name = $name.".".$file_expensions; // this is new name of the image
move_uploaded_file($file_tmp, "path/$name")
I assume you are aware that the code you've presented here allows anyone with upload privileges to upload and execute PHP code.
(the reason I mention this is that there is scope for a lot of improvement elsewhere - and if the security vulnerability is exploitable then you should really think about start again from scratch with this).
Will your extension always be .jpg or .png ? (what about .jpeg ?)
I need to rename the image name to be like the txt. name file
I presume you mean that you want the filename on the retained image file to match that of the txt file - you can specify the destination name in move_uploaded_file(). Breaking down a process into steps is a good idea for managing complexity but file operations are expensive and here redundant.
So really you want to know how to get the a filename without an extension then add the file extension from a different file.
You already have the extension you want to apply in $Image_extension
While you could just do....
$destination_name=$destination_path
. str_replace('.txt', '.' . $image_extension, $Textfile_name);
However this will not work as expected if $imageFile_name contains more than one instance of '.txt'.
You could use PCREs to specify that you should only apply the change to the end of the string:
$destination_name=preg_replace("/txt$/i", $image_extension, $Textfile_name);
Or take the last 4 characters off $Textfile_name then append the image extension.
$destination_name=substr($Textfile_name, 0, -3) . $image_extension;
Or strrev the text file name, replace 'txt' with strrev($image_extension) with a limit of 1, then strrev the result to ensure only the end of the string is replaced.
If I spent more time thinking about this, there are probably other solutions too - but they will become increasingly esoteric.
In general, allowing users to pick their own names (or even part thereof) for content uploaded inside the document root is a bad idea.

Random rename all files

I am trying to write a script that does the following but I am unsure where to start:
Gets all the files in a dir - both *.JPG and *.jpg
Renames the above files starting from 00 - using the RANDOM() function and saves them as .JPG
Displays a success message when done.
Currently they are "RANDOM_FILENAME.JPG or .jpg" I am wanting ranNum.JPG in the end a random image with a random number
I know that I will have to get all the files in the folder and possibly explode them but I just confused at the best 5.* way to do this
Try something like this:
// getting the list of files
$files = glob('my/dir/*.[jJ][pP][gG]');
foreach($files as $file)
{
// here: trying to find a random name.
// repeat, if such a file already exists
do {
$number = mt_rand(0, 999999);
$new_name = dirname($file) .'/'. sprintf("%06d", $number) .'.JPG';
}
while(is_file($new_name));
// now, all we need is love!
rename ($file, $new_name);
}
echo "Successfully renamed ".count($files)." files!";
This will rename them randomly, like 528989.JPG, 112344.JPG, 003424.JPG, etc.

Adding 1 to the image name every time a new image is uploaded to folder

I am a newbie at PHP and I'm learning.
I've made a basic script where you can upload an image to a director on the server. I want the image names to get a number at the end so that the name won't be duplicated.
This is my script to add 1 to the name (I'm really bad at "for loops"):
for(x=0; $imageName => 50000; x++){
$imageFolderName = $imageName.$x;
}
Please tell me if I'm doing this totally wrong.
Adding to Niet's answer, you can do a foreach loop on all the files in your folder and prepend a number to the file name like so:
<?
$directory = 'directory_name';
$files = array_diff(scandir($directory), array('.', '..'));
$count = 0;
foreach($files as $file)
{
$count++;
rename($file, $count.'-'.$file);
}
?>
Alternatively you could rename the file to the timestamp of when it was uploaded and prepend some random characters to the file with the rand() function:
<?
$uploaded_name = 'generic-image.jpeg';
$new_name = time().rand(0, 999).$uploaded_name;
?>
You'll need to handle and move the uploaded files before and after the rename, but you get the general gist of how this would work.
Here's a potential trick to avoid looping:
$existingfiles = count(glob("files/*"));
// this assumes you are saving in a directory called files!
$finalName = $imageName.$existingfiles;

Categories