How to unlink() by its name without knowing the file extention? - php

In short
We have a a file called clients.(unique parameter). And now we want to unlink() it, but as we don't know the file extension, how do we succeed?
Longer story
I have a cache system, where the DB query in md5() is the filename and the cache expiration date is the extension.
Example: 896794414217d16423c6904d13e3b16d.3600
But sometimes the expiration dates change. So for the ultimate solution, the file extension should be ignored.
The only way I could think of is to search the directory and match the filenames, then get the file extension.

Use a glob():
$files = glob("/path/to/clients.*");
foreach ($files as $file) {
unlink($file);
}
If you need to, you can check the filemtime() of each file returned by the glob() to sort them so that you only delete the oldest, for example.
// Example: Delete those older than 2 days:
$files = glob("./clients.*");
foreach ($files as $file) {
if (filemtime($file) < time() - (86400 * 2)) {
unlink($file);
}
}

You are correct in your guess to search the directory for a matching file name. There are multiple approaches you could take:
readdir the folder in question
glob as suggested by Micheal
You could also get the output of ls {$target_dir} | grep {$file_first_part} and then unlink the resulting string (assuming a match is found).

Related

stripos vs glob for unlinking

I want to delete the files which are not appearing in this array. I know the name of file partially but don't know the size parameter suffixed after file name like filename-50x75.jpg, filename-100x77.jpg , filename-500x377.jpg.
I want to delete above images from a directory and don't want to delete below images.
$list_of_allowed_images=array("filename-50x50.jpg","filename-50x70.jpg","filename-90x50.jpg","filename-100x100.jpg","filename-150x150.jpg","filename-250x200.jpg","filename-300x250.jpg","filename-360x270.jpg","filename-390x250.jpg","filename-500x345.jpg","filename-768x576.jpg","filename-820x400.jpg","filename-1024x768.jpg");
I have the following snippet:
foreach(glob($base_path_del.$only_obs_img."[0-9][0-9]*x*.{jpg,gif,png}", GLOB_BRACE) as $file_to_del_now)
{
if(!in_array($file_to_del_now,$list_of_allowed_images))
{
unlink($file_to_del_now);
}
}
but I think it can be more efficient. Is another more efficient way to do this?
Here's what I recommend:
(untested code)
chdir($base_path_del);
$files = glob($only_obs_img."[0-9][0-9]*x*.{jpg,gif,png}", GLOB_BRACE);
$whitelist_regex = "/-(?:50x[57]0|90x50|100x100|150x150|250x200|300x250|360x270|390x250|500x345|768x576|820x400|1024x768)\.jpg$/i";
$removables = preg_grep($whitelist_regex, $files, PREG_GREP_INVERT);
foreach ($removables as $filename) {
unlink($filename);
}
So...
Change the current working directory so that glob() doesn't include the paths in the collection of qualifying files.
Invert preg_grep() so that files that don't match the whitelist regex requirements are retained.
Then just loop the naughty list and delete the lot.
The regex pattern boils down your whitelist array logic. The check starts at the last - in the filename, checks the dimensions, checks .jpg case-insensitively, then ensures that the filename has ended.
p.s. or array_map() if you don't want to break the functional style.
array_map('unlink', $removables);

Rename Many Files in a Folder - PHP

I have 2500 images in a Folder, which has NAME word in all the images. For examples
Peter Wang B5357550.jpg
Sander Mackiney B5355624.jpg
what i need to do is read all the filenames and rename it to the following
B5357550.jpg
B5355624.jpg
So remove NAME and SURNAME from filename, is it possible in PHP to do bulk renaming ?
(All student IDs are in format of Bxxxxxxx)
Quick, simple solution:
$dir = $_SERVER['DOCUMENT_ROOT'].'/your-folder-to-files';
$files = scandir($dir);
unset($files[0],$files[1]);
foreach ($files as $oldname){
$newname = substr($oldname, -12);
rename ($dir.'/'.$oldname, $dir.'/'.$newname);
}
N.B.: You may need to change the server path to something similar to:
$dir = "/home/users/you/folder_files/";
or
$dir = "folder_files/";
If $_SERVER['DOCUMENT_ROOT'] does not work for you.
If they're all in that format, it would be simple to fix, yes. Run glob to get all the .jpg files into an array, then simply explode the filename on spaces, use a foreach loop on that array, use end to get the last section, and rename the file to that string.

Using 'glob' to display files with no extension?

I am using the following code to display the files in descending order of date. But When I upload any file without extension its not visible because of glob, is there any way to show the hidden files?
Code:
<?php
$dir = "/opt/lampp/htdocs/jquery";
chdir($dir);
array_multisort(array_map('filemtime', ($files = glob("*.*"))), SORT_DESC, $files);
foreach($files as $filename)
{
echo "<li>".$filename."</li>";
}
?>
#bodi0 gave you the code for ONLY items with no dots, you might be looking for
...glob("*")
to get all files.
Then, you will need to remove "." and ".."
This is impossible with inclusive only glob (python), the answerers (is that a word), misunderstood your question.
/* gets all files/folders and returns folders with no "/" at the end, /*/ gets only folders and adds the "/" at the end, but for files with NO extension ie path/foo (NO DOT) it is not straightforward to separate the files from the folders with glob.
It is possible, of course, just pass this regex pattern to the glob():
glob("([^\.])");
The pattern ([^\.]) means every file name, which does not have a dot in it.

How to limit the number of files returned by glob to save memory?

I made program to ocassionally scan directory and then delete old cache files.
Often the number of cache files are quite huge and I got out of memory error.
glob(cacheme_directory()."*");
How do I make glob to return limited number of files? Say first 50000. Then we will delete them and then at the next session we can delete again, etc.
This is not the same with Limit number of results for glob directory/folder listing
I need to reduce amount of memory used. Hence loading the whole thing and then removing things won't work.
This is the full program
if (mt_rand(0,1000)==0)
{
$files = glob(cacheme_directory()."*");
foreach($files as $file)
{
$filemtime=filemtime ($file);
if (is_file($file) && time()-$filemtime>= $cacheAge)
{
unlink($file);
}
}
}
Try it with DirectoryIterator (PHP >= 5) :
$i = new DirectoryIterator( cacheme_directory() );
foreach ($i as $val) {
if ($val->isFile()) {
echo "{$val->getFilename()} ({$val->getMTime()})\n";
}
}
Glob will return you an array of the entire directory, you can't change that.
To read only a limited number of files into memory, check the opendir function in PHP, which let's you write your own loop on a resource.
You can not do it with glob. However you can use some wild card tricks. Like
glob(cacheme_directory()."1*");
This is return about one-tenth of files if their name starts only with numbers. If they hold only alphabetic characters you can use a* to get one-twenty-sixth of file names.
You can loop it.
for($i=0;$i<10;$i++){
glob(cacheme_directory()."$i*");
}
or
for($i=ord('a');$i<=ord('z');$i++){
glob(cacheme_directory().chr($i)."*");
}
Like #Dutow said: glob will return you an array of the entire directory, you can't change that.
An alternative to looping through the directory with PHP is to simply issue a shell command like:
find /path/to/cache/dir/ -type f -delete
Which will delete all files in the given directory. Or you can match certain names like:
find /path/to/cache/dir/ -type f -name 'cache*' -delete
This assumes you have access to either the shell() or shell_exec() commands, but will not require gobs of memory, and can be backgrounded by tacking on the & operator at the end of the command.

PHP Cut unknown file extensions

I need help about file manipulation in PHP.
I have 4 file with known names and UNKNOWN extensions.
Like that:
Y923BBBB.E120506
Y924BBBB.E120606
Y925BBBB.E120706
Y926BBBB.E120806
and the file extensions changes everyday.
How i can cut or strip for every file the file extension, so that will stay only the names like that:
Y923BBBB
Y924BBBB
Y925BBBB
Y926BBBB
Anybody an idea?
Think about it the other way around: you want to extract the filename, not "delete the extension":
echo pathinfo($file, PATHINFO_FILENAME);
http://php.net/pathinfo
Use strrpos to find the last . and substr to get only the substring up to that point. To find the files and rename them, use glob and rename:
foreach(glob('*') as $f) {
if ($f == '.' || $f == '..') continue;
$stripped = substr($f, 0, strrpos($f, '.'));
rename($f, $stripped);
}
Take care that glob('*') works differently on windows and linux (compare with answer). Use DirectoryIterator instead if you want a more stable code. Also that one provides the needed functions already to process the file-extension and won't break - as in this example - when a file does not have a dot inside. And take real care with rename, using glob returns the file-name only, rename handles this as full path, you will move files to locations you might not want to move them.
foreach(new DirectoryIterator('.') as $f) {
/* #var $f splFileInfo*/
if (!$f->isFile()) continue;
($ext = strlen($f->getExtension())) && $ext++;
if (!$ext) continue;
$path = $f->getRealPath();
rename($path, substr($path, 0, -$ext));
}
Take care. You should always takes care with rename operations. Every operation related to the file-system and changing it needs more care as let's say read-only proceedings.

Categories