Scandir newest files in array with limit - php

I have made a PHP script to scan a directory, it lists all filenames in an array with a limit of 20. Now its displaying only the beginning of the array. So if there are 40 files, it displays only the first 0-20 but we need 20-40.. Can someone help me ? Thanks!!
<?php
$files = glob('data/*.{png}', GLOB_BRACE);
usort($files, 'filemtime_compare');
function filemtime_compare($a, $b)
{
return filemtime($a) - filemtime($b);
}
$i = 0;
$show = 20;
foreach($files as $file)
{
if($i == $show) {
break;
} else {
++$i;
}
$var .= $file . "\n";
}
$fp = fopen("data.txt", "wb");
fwrite($fp, $var);
fclose($fp);
echo $var;
?>

You could use array_chunk() to split the $files array up in chunks of 20 files. Then use implode() to format the values in a chunk to a single string. Replace the foreach loop with this:
$show = 20;
$files = array_chunk($files, $show);
$page = 0; // page 0 is 0-19, page 1 is 20-39, etc.
$var = implode("\n", $files[$page]);
Edit: For the last 20 files you could use array_slice():
$files = array_slice($files, -20);
$var = implode("\n", $files);

Related

How to apply code on multiple files at once?

I couldn't find a solution to this. I'm sorry if this is a silly question.
I have 4 log files and I need to remove all log except last 10 lines.
I'm able to do it for 1 file but how to apply it on 4 files using once simple php code?
My current code:
<?php
$lines_array = file("log.txt");
$lines = count($lines_array);
$new_output = "";
for ($i=$lines - 10; $i < $lines; $i++) {
$new_output .= $lines_array[$i];
}
$filename = "log.txt";
file_put_contents($filename,$new_output);
What is the best way to achieve this?
Functional programming to the rescue:
function rotate(string $filename)
{
$lines_array = file($filename);
$lines = count($lines_array);
$new_output = "";
for ($i=$lines - 10; $i < $lines; $i++) {
$new_output .= $lines_array[$i];
}
file_put_contents($filename,$new_output);
}
rotate('log1.txt');
rotate('someOtherLog.txt');
rotate('third/log/file.txt);
//etc.
// or,
$logs = [
'log1.txt',
'someOtherLog.txt',
'third/log/file.txt'
];
foreach($logs as $file) {
rotate($file);
}
This allows you to write the code for rotating your logs one time, which makes your code better by being DRY (Don’t Repeat Yourself)
List your logfiles in an array, and loop over it, rewriting the log files as you go:
$logs = [
'log1.txt',
'log2.txt',
'log3.log'
];
foreach($logs as $log) {
// Only do this if we read the file.
if ($logData = file($log)) {
// array_slice takes a portion of the array
file_put_contents($log, array_slice($logData,-10));
}
}
Please try this code:
<?php
$fp = fopen("log.txt","ab+");
$data = fread($fp,filesize("log.txt"));
$data_array = explode("\n",$data);
$new_data = array();
for($i = count($data_array) - 1; $i >= count($data_array) - 10;$i--)
{
array_push($new_data , $data_array[$i]);
}
fclose($fp);
$new_data_array = array_reverse($new_data);
$data = implode("\n",$new_data_array);
$fp = fopen("log.txt","w");
fwrite($fp,$data);
fclose($fp);
?>

Count all resulting values outside foreach loop

I would like to count all characters in text files in certain path, so i've wrote the following code
<?PHP
$files = glob('my/files/path/*.txt', GLOB_BRACE);
foreach($files as $file) {
$str = file_get_contents($file) or dir("can not read file");
$numCharSpace = strlen($str);
echo "Counted " .$numCharSpace. " character(s).<br>";
}
?>
Let say, we have 4 files inside this path so it will print out the following
Counted 201 character(s).
Counted 99 character(s).
Counted 88 character(s).
Counted 112 character(s).
How can i get the total of all which should be 500 character(s) so how to print out the count of all results which are inside foreach(); loop.
With strlen you get the number of the bytes of the file. So, you can as well get that directly, without the need to read the file contents.
$numberOfChars = array_sum(
array_map('filesize', glob('my/files/path/*.txt', GLOB_BRACE))
);
What this does is get the file size for each one of the files returned by glob, and sum them using array_sum.
You can use a variable to sum. Then you could use filesize() to get total bytes of the file instead of load it:
$files = glob('my/files/path/*.txt', GLOB_BRACE);
$total = 0;
foreach($files as $file) {
$numCharSpace = filesize($file);
$total += $numCharSpace ;
}
echo "Counted " .$total. " character(s).<br>";
<?PHP
$files = glob('my/files/path/*.txt', GLOB_BRACE);
$Total = 0;
foreach($files as $file) {
$str = file_get_contents($file) or dir("can not read file");
$numCharSpace = strlen($str);
echo "Counted " .$numCharSpace. " character(s).<br>";
$Total += $numCharSpace;
}
echo "Total " .$Total. " characters.<br>";
?>
Following code should work :
$files = glob('my/files/path/*.txt', GLOB_BRACE);
$numCharSpace = 0;
foreach($files as $file) {
$str = file_get_contents($file) or dir("can not read file");
$numCharSpace = $numCharSpace + strlen($str);
}
echo "Counted " .$numCharSpace. " character(s).";

How to read specific line text with interval using PHP

i want read line in text file, with interval 4 , 4 lines show per page..
if load domain.com/pages/page2.php
output read line (5,6,7,8)
if load domain.com/pages/page3.php
output read line (9,10,11,12)
my code
$file1 = basename($_SERVER["SCRIPT_FILENAME"], '.php') ;
$file1 = preg_replace("/.+?(\\d+).*/", "$1", $file1);
$file2 = ($file1 - 1);
$file3 = ($file2 *4);
$file4 = ($file3 + 3 );
function retrieveText($file, $init, $end, $sulfix = '')
{
$i = 1;
$output = '';
$handle = fopen($file, 'r');
while (false === feof($handle) && $i <= $end) {
$data = fgets($handle);
if ($i >= $init) {
$output .= $data . $sulfix;
}
$i++;
}
fclose($handle);
return $output;
}
echo retrieveText('file.txt', $file3, $file4, '<br>');
not work, missing lines
First of all, I'm gonna advise you to get rid of your REGEX name getter and just have the following format:
domain.com/pages?page=1
domain.com/pages?page=2
domain.com/pages?page=3
So on and so forth. You will be using $_GET['page'] to retrieve the page number.
Now, the way that I'd go with it is to have an array with all the lines of the text and to use the array_slice() function. Something along this should do:
function retrieveText($file, $page, $per_page, $suffix)
{
$content = file_get_contents($file);
$array = explode(PHP_EOL, $content);
$start = --$page * $per_page;
$lines = array_slice($array, $start, $per_page);
$output = '';
foreach ($lines as $line) {
$output .= $line . $suffix;
}
return $output;
}
You should then call this function like this:
$page = $_GET['page'];
$page = $page === null ? 1 : $page;
retrieveText('file.txt', $page, 4, '<br>');

Array isn't sorting when writing to file

I wrote this script:
<?PHP
$file_handle = fopen("info.txt", "rb");
while (!feof($file_handle) ) {
$line_of_text = fgets($file_handle);
$parts[] = explode('|', $line_of_text);
}
fclose($file_handle);
$a = $parts;
function cmp($a,$b){
return strtotime($a[8])<strtotime($b[8])?1:-1;
};
uasort($a, 'cmp');
$failas = "dinfo.txt";
$fh = fopen($failas, 'w');
for($i=0; $i<count($a); $i++){
$txt=implode('|', $a[$i]);
fwrite($fh, $txt);
}
fclose($fh);
?>
When I use:
print_r($a);
after
uasort($a, 'cmp');
Then I can see sorted array. But when I write to file using these commands:
$fh=fopen($failas, 'w');
for($i=0; $i<count($a); $i++){
$txt=implode('|', $a[$i]);
fwrite($fh, $txt);
}
fclose($fh);
It shows not sorted information, what am I doing wrong?
This should work for you:
Here I first get your file into an array with file() where every line is one array element. There I ignore empty lines and new line characters at the end of each line.
After this I sort the array with usort(). Where I first get all dates and times from each line by explode()'ing it. After this I simply get the timestamp of each date with strtotime() and compare it which each other.
At the end I simply save the file with file_put_contents(), where I also add a new line character at the end of each line with array_map().
<?php
$lines = file("test.txt", FILE_SKIP_EMPTY_LINES | FILE_IGNORE_NEW_LINES);
usort($lines, function($a, $b){
list($aDate, $aTime) = explode(" ", explode("|", $a)[substr_count($a, "|")]);
list($bDate, $bTime) = explode(" ", explode("|", $b)[substr_count($b, "|")]);
if(strtotime("$aDate $aTime") == strtotime("$bDate $bTime"))
return 0;
return strtotime("$aDate $aTime") < strtotime("$bDate $bTime") ? 1 : -1;
});
file_put_contents("test.txt", array_map(function($v){return $v . PHP_EOL;}, $lines));
?>
Side notes:
I would recommend you to save this data in a database where it is much flexible to sort and getting the data!
EDIT:
For people which have a php version (echo phpversion();) under <5.3, just change the anonymous functions to normal functions and pass the function name as strings like this:
<?php
$lines = file("test.txt", FILE_SKIP_EMPTY_LINES | FILE_IGNORE_NEW_LINES);
function timestampCmp($a, $b) {
$aExploded = explode("|", $a);
$bExploded = explode("|", $b);
list($aDate, $aTime) = explode(" ", $aExploded[substr_count($a, "|")]);
list($bDate, $bTime) = explode(" ", $bExploded[substr_count($b, "|")]);
if(strtotime("$aDate $aTime") == strtotime("$bDate $bTime"))
return 0;
return strtotime("$aDate $aTime") < strtotime("$bDate $bTime") ? 1 : -1;
}
function addEndLine($v) {
return $v . PHP_EOL;
}
usort($lines, "timestampCmp");
file_put_contents("test.txt", array_map("addEndLine", $lines));
?>

Count how many files in directory PHP

I'm working on a slightly new project. I wanted to know how many files are in a certain directory.
<div id="header">
<?php
$dir = opendir('uploads/'); # This is the directory it will count from
$i = 0; # Integer starts at 0 before counting
# While false is not equal to the filedirectory
while (false !== ($file = readdir($dir))) {
if (!in_array($file, array('.', '..') and !is_dir($file)) $i++;
}
echo "There were $i files"; # Prints out how many were in the directory
?>
</div>
This is what I have so far (from searching). However, it is not appearing properly? I have added a few notes so feel free to remove them, they are just so I can understand it as best as I can.
If you require some more information or feel as if I haven't described this enough please feel free to state so.
You can simply do the following :
$fi = new FilesystemIterator(__DIR__, FilesystemIterator::SKIP_DOTS);
printf("There were %d Files", iterator_count($fi));
You can get the filecount like so:
$directory = "/path/to/dir/";
$filecount = count(glob($directory . "*"));
echo "There were $filecount files";
where the "*" is you can change that to a specific filetype if you want like "*.jpg" or you could do multiple filetypes like this:
glob($directory . "*.{jpg,png,gif}",GLOB_BRACE)
the GLOB_BRACE flag expands {a,b,c} to match 'a', 'b', or 'c'
Note that glob() skips Linux hidden files, or all files whose names are starting from a dot, i.e. .htaccess.
Try this.
// Directory
$directory = "/dir";
// Returns an array of files
$files = scandir($directory);
// Count the number of files and store them inside the variable..
// Removing 2 because we do not count '.' and '..'.
$num_files = count($files)-2;
You should have :
<div id="header">
<?php
// integer starts at 0 before counting
$i = 0;
$dir = 'uploads/';
if ($handle = opendir($dir)) {
while (($file = readdir($handle)) !== false){
if (!in_array($file, array('.', '..')) && !is_dir($dir.$file))
$i++;
}
}
// prints out how many were in the directory
echo "There were $i files";
?>
</div>
The best answer in my opinion:
$num = count(glob("/exact/path/to/files/" . "*"));
echo $num;
It doesnt counts . and ..
Its a one liner
Im proud of it
Since I needed this too, I was curious as to which alternative was the fastest.
I found that -- if all you want is a file count -- Baba's solution is a lot faster than the others. I was quite surprised.
Try it out for yourself:
<?php
define('MYDIR', '...');
foreach (array(1, 2, 3) as $i)
{
$t = microtime(true);
$count = run($i);
echo "$i: $count (".(microtime(true) - $t)." s)\n";
}
function run ($n)
{
$func = "countFiles$n";
$x = 0;
for ($f = 0; $f < 5000; $f++)
$x = $func();
return $x;
}
function countFiles1 ()
{
$dir = opendir(MYDIR);
$c = 0;
while (($file = readdir($dir)) !== false)
if (!in_array($file, array('.', '..')))
$c++;
closedir($dir);
return $c;
}
function countFiles2 ()
{
chdir(MYDIR);
return count(glob("*"));
}
function countFiles3 () // Fastest method
{
$f = new FilesystemIterator(MYDIR, FilesystemIterator::SKIP_DOTS);
return iterator_count($f);
}
?>
Test run: (obviously, glob() doesn't count dot-files)
1: 99 (0.4815571308136 s)
2: 98 (0.96104407310486 s)
3: 99 (0.26513481140137 s)
Working Demo
<?php
$directory = "../images/team/harry/"; // dir location
if (glob($directory . "*.*") != false)
{
$filecount = count(glob($directory . "*.*"));
echo $filecount;
}
else
{
echo 0;
}
?>
I use this:
count(glob("yourdir/*",GLOB_BRACE))
<?php echo(count(array_slice(scandir($directory),2))); ?>
array_slice works similary like substr function, only it works with arrays.
For example, this would chop out first two array keys from array:
$key_zero_one = array_slice($someArray, 0, 2);
And if You ommit the first parameter, like in first example, array will not contain first two key/value pairs *('.' and '..').
Based on the accepted answer, here is a way to count all files in a directory RECURSIVELY:
iterator_count(
new \RecursiveIteratorIterator(
new \RecursiveDirectoryIterator('/your/directory/here/', \FilesystemIterator::SKIP_DOTS)
)
)
$it = new filesystemiterator(dirname("Enter directory here"));
printf("There were %d Files", iterator_count($it));
echo("<br/>");
foreach ($it as $fileinfo) {
echo $fileinfo->getFilename() . "<br/>\n";
}
This should work
enter the directory in dirname. and let the magic happen.
Maybe usefull to someone. On a Windows system, you can let Windows do the job by calling the dir-command. I use an absolute path, like E:/mydir/mysubdir.
<?php
$mydir='E:/mydir/mysubdir';
$dir=str_replace('/','\\',$mydir);
$total = exec('dir '.$dir.' /b/a-d | find /v /c "::"');
$files = glob('uploads/*');
$count = 0;
$totalCount = 0;
$subFileCount = 0;
foreach ($files as $file)
{
global $count, $totalCount;
if(is_dir($file))
{
$totalCount += getFileCount($file);
}
if(is_file($file))
{
$count++;
}
}
function getFileCount($dir)
{
global $subFileCount;
if(is_dir($dir))
{
$subfiles = glob($dir.'/*');
if(count($subfiles))
{
foreach ($subfiles as $file)
{
getFileCount($file);
}
}
}
if(is_file($dir))
{
$subFileCount++;
}
return $subFileCount;
}
$totalFilesCount = $count + $totalCount;
echo 'Total Files Count ' . $totalFilesCount;
Here's a PHP Linux function that's considerably fast. A bit dirty, but it gets the job done!
$dir - path to directory
$type - f, d or false (by default)
f - returns only files count
d - returns only folders count
false - returns total files and folders count
function folderfiles($dir, $type=false) {
$f = escapeshellarg($dir);
if($type == 'f') {
$io = popen ( '/usr/bin/find ' . $f . ' -type f | wc -l', 'r' );
} elseif($type == 'd') {
$io = popen ( '/usr/bin/find ' . $f . ' -type d | wc -l', 'r' );
} else {
$io = popen ( '/usr/bin/find ' . $f . ' | wc -l', 'r' );
}
$size = fgets ( $io, 4096);
pclose ( $io );
return $size;
}
You can tweak to fit your needs.
Please note that this will not work on Windows.
simple code add for file .php then your folder which number of file to count its
$directory = "images/icons";
$files = scandir($directory);
for($i = 0 ; $i < count($files) ; $i++){
if($files[$i] !='.' && $files[$i] !='..')
{ echo $files[$i]; echo "<br>";
$file_new[] = $files[$i];
}
}
echo $num_files = count($file_new);
simple add its done ....

Categories