Find the largest number in file names on a web server

On my web server, I have a folder with numbered image files:

... 296.jpg 297.png 298.gif ... 

Numbers are consecutive (1, 2, 3, ...). The file name contains only the number ("12.jpg", not "photo_12.jpg"). Files cannot be created and saved in the order of their file name numbering (i.e. 2000.jpg may be older than 2.jpg).

I want to find the largest number in file names.

I'm doing it:

 $glob = glob("path/to/dir/*"); $highest = max(preg_replace("|[^0-9]|", "", $glob)); // $highest is now something like 381554 

Is there a less heavy resource method?

+6
source share
6 answers

First of all, you need to decide what resources you want to save, because there will be different approaches depending on whether it is memory, I / O operations of something else.

So far, you are most optimized in terms of working speed, but its memory takes a lot of time, since there can be many files in a folder and you will fall into the limits of memory.

I suggest you max cache somewhere, for example in Redis. And then refresh it every time you upload a new image. To cache it, you must first get it. You can get the initial maximum value either with a simple script:

 $max = 0; foreach (new DirectoryIterator('.') as $fileInfo) { if ($fileInfo->isDot()) continue; $current = pathinfo($fileInfo->getFilename())['filename']; if (!is_numeric($current)) continue; if ($current > $max) $max = $current; } 

Or by calling the external sort command as Wladyslaw-Savchenko .

Then you only need to update the maximum value. Update it either at each boot, or in cron of both.

+2
source

It could be a working way.

 $numeric_files=glob("[0-9]*.*"); $slike = array_map(function($e){return pathinfo($e, PATHINFO_FILENAME);}, $numeric_files); echo max($slike); 
+2
source

Beginning with

 $path = "path/to/dir/"; 

Lets get a file array

// $ myfile

 if ($handle = opendir($path)) { while (false !== ($entry = readdir($handle))) { if ($entry != "." && $entry != "..") { if(!is_dir($entry)){ $myFile[] = substr($entry,0,strrpos($entry, ".")); } } } closedir($handle); } 

Then we can sort the array

 rsort($myFile,SORT_NUMERIC); 

The first will be the one we were looking for

 print $myFile[0]; 

This is an example and not verified.

+1
source

I do not think this will lead to a good solution. Especially with a large number of files, which I assume due to your comment that the largest number is about 381 thousand. This will lead to a high level of input / output and, possibly, real performance when you have too many visitors and / or slow / high load a server, possibly with an older hard drive, which is common for storing images.

I would advise you to store the file names in the database. Even if you are not using the database yet, this is the best solution because you can get the highest number with a clean SQL query, which will result in a significantly lower I / O load instead of scanning huge directories in the file system. Then you can profit from indexes that once again optimize the speed of our database queries.

It is not necessary to store the full path and even a bad idea when you have all the files in one folder. In this case, you will receive an unnecessary excess amount that the storage will subside and do additional work when you may want to change the path later. It is better to store only the file names and create a constant in our configuration or script for a path such as

 define('IMAGE_PATH', '/var/www/images'); 

If you want to go to the selected image, you can do something like this:

 $fullImagePath = IMAGE_PATH . $databaseQueryResult['fileName']; 

I donโ€™t know what you want to do, but it might be nice to think about your design when you are not already using the database. Something in the area of โ€‹โ€‹image hosting looks like a database might be a good idea here, as well as for other features that you can implement.

+1
source

You can use something like this:

 $path = 'path_to_directory'; $command = 'ls ' . escapeshellarg($path) . ' | sort -rn | head -1'; if (!($output = system($command))) { print 'Error during execution of: "' . $command . '"'; } print $output; 
+1
source

Here is what I got with my binary search comment.

It does not need memory and takes only 0.003 seconds and 35 files with 100,000 files.

I think you could code it in PHP or put it on it.

 #!/bin/bash checkfile(){ if [ -f "$1.jpg" ]; then echo DEBUG: Testing ${i}.jpg, exists - so move min marker to $1 min=$1 return 0 else echo DEBUG: Testing ${i}.jpg, nope - so move max marker to $1 max=$1 return 1 fi } i=1 min=0 max=-1 while : ; do if checkfile $i && [[ $max -eq -1 ]]; then ((i*=2)) else ((i=(max+min)/2)) fi diff=$((max-min)) [[ $diff -eq 1 ]] && break done echo Result:$min 

Output:

 DEBUG: Testing 1.jpg, exists - so move min marker to 1 DEBUG: Testing 2.jpg, exists - so move min marker to 2 DEBUG: Testing 4.jpg, exists - so move min marker to 4 DEBUG: Testing 8.jpg, exists - so move min marker to 8 DEBUG: Testing 16.jpg, exists - so move min marker to 16 DEBUG: Testing 32.jpg, exists - so move min marker to 32 DEBUG: Testing 64.jpg, exists - so move min marker to 64 DEBUG: Testing 128.jpg, exists - so move min marker to 128 DEBUG: Testing 256.jpg, exists - so move min marker to 256 DEBUG: Testing 512.jpg, exists - so move min marker to 512 DEBUG: Testing 1024.jpg, exists - so move min marker to 1024 DEBUG: Testing 2048.jpg, exists - so move min marker to 2048 DEBUG: Testing 4096.jpg, exists - so move min marker to 4096 DEBUG: Testing 8192.jpg, exists - so move min marker to 8192 DEBUG: Testing 16384.jpg, exists - so move min marker to 16384 DEBUG: Testing 32768.jpg, exists - so move min marker to 32768 DEBUG: Testing 65536.jpg, exists - so move min marker to 65536 DEBUG: Testing 131072.jpg, nope - so move max marker to 131072 DEBUG: Testing 98304.jpg, exists - so move min marker to 98304 DEBUG: Testing 114688.jpg, nope - so move max marker to 114688 DEBUG: Testing 106496.jpg, nope - so move max marker to 106496 DEBUG: Testing 102400.jpg, nope - so move max marker to 102400 DEBUG: Testing 100352.jpg, nope - so move max marker to 100352 DEBUG: Testing 99328.jpg, exists - so move min marker to 99328 DEBUG: Testing 99840.jpg, exists - so move min marker to 99840 DEBUG: Testing 100096.jpg, nope - so move max marker to 100096 DEBUG: Testing 99968.jpg, exists - so move min marker to 99968 DEBUG: Testing 100032.jpg, nope - so move max marker to 100032 DEBUG: Testing 100000.jpg, exists - so move min marker to 100000 DEBUG: Testing 100016.jpg, nope - so move max marker to 100016 DEBUG: Testing 100008.jpg, nope - so move max marker to 100008 DEBUG: Testing 100004.jpg, nope - so move max marker to 100004 DEBUG: Testing 100002.jpg, nope - so move max marker to 100002 DEBUG: Testing 100001.jpg, nope - so move max marker to 100001 Result:100000 
0
source

Source: https://habr.com/ru/post/979901/


All Articles