Passing array to file()? - php

I have a directory containing a changeable number of files, each of which contains a single character on the first line, and CSV for the remaining file content, such as:
U
Status4,jwalker,Tech Manual 03264
Status3,jwalker,Status Report 3213
Status4,rmartino,Tech Manual 52002
...
Using this code, I can easily get a listing of the all report filenames in a directory:
<?php
// Open session
session_start();
// Get array of reports from directory
$files = scandir('reports');
$files <= array_pop($files);
$files <= array_shift($files);
$files <= array_shift($files);
// Extract summaries
for ($i=0; $i <= count($files)-1; $i++) {
$summaries[$i] = file($files[$i]);
}
?>
The reason I would like to use the file() function in line 13 is because it would conveniently break the file into an array so I could easily reference a particular line, such as $summaries[3][2] to get the third line from the fourth file in the directory (remembering that I'm counting from the PHP default 0 here). The PHP.net documentation doesn't indicate anything about NOT using an array as the string to be passed to file(), so I would assume there is a way to do it. But I've only found constants and strings, not arrays being passed.
Anyone have any insight here? Much thanks!

There's no issue with passing the value of an array element $arr[$k] to file() as long as it's a string that represents a file path.
The problem is you're scanning the reports folder, and getting a list of file names not file paths. You need to prepend reports to the file name. Not doing so should cause an exception when file() can't find the file.
<?php
// Open session
session_start();
// Get array of reports from directory
$files = scandir('reports');
// Extract summaries
for ($i=0; $i <= count($files)-1; $i++) {
if ($files[$i] == '.' || $files[$i] == '..') continue;
$summaries[$i] = file('reports' . DIRECTORY_SEPARATOR . $files[$i]);
}
?>
Also, not sure what the following is meant to be doing, but what it's actually doing is removing the last file, I've omitted it in my answer
$files <= array_pop($files);
The following two lines are presumably removing . and .. paths, I've replaced those with a check in the loop.
$files <= array_shift($files);
$files <= array_shift($files);

Related

PHP If-Else does not work for comparing filecontents

I am trying to make a PHP application which searches through the files of your current directory and looks for a file in every subdirectory called email.txt, then it gets the contents of the file and compares the contents from email.txt with the given query and echoes all the matching directories with the given query. But it does not work and it looks like the problem is in the if-else part of the script at the end because it doesn't give any output.
<?php
// pulling query from link
$query = $_GET["q"];
echo($query);
echo("<br>");
// listing all files in doc directory
$files = scandir(".");
// searching trough array for unwanted files
$downloader = array_search("downloader.php", $files);
$viewer = array_search("viewer.php", $files);
$search = array_search("search.php", $files);
$editor = array_search("editor.php", $files);
$index = array_search("index.php", $files);
$error_log = array_search("error_log", $files);
$images = array_search("images", $files);
$parsedown = array_search("Parsedown.php", $files);
// deleting unwanted files from array
unset($files[$downloader]);
unset($files[$viewer]);
unset($files[$search]);
unset($files[$editor]);
unset($files[$index]);
unset($files[$error_log]);
unset($files[$images]);
unset($files[$parsedown]);
// counting folders
$folderamount = count($files);
// defining loop variables
$loopnum = 0;
// loop
while ($loopnum <= $folderamount + 10) {
$loopnum = $loopnum + 1;
// gets the emails from every folder
$dirname = $files[$loopnum];
$email = file_get_contents("$dirname/email.txt");
//checks if the email matches
if ($stremail == $query) {
echo($dirname);
}
}
//print_r($files);
//echo("<br><br>");
?>
Can someone explain / fix this for me? I literally have no clue what it is and I debugged soo much already. It would be heavily gracious and appreciated.
Kind regards,
Bluppie05
There's a few problems with this code that would be preventing you from getting the correct output.
The main reason you don't get any output from the if test is the condition is (presumably) using the wrong variable name.
// variable with the file data is called $email
$email = file_get_contents("$dirname/email.txt");
// test is checking $stremail which is never given a value
if ($stremail == $query) {
echo($dirname);
}
There is also an issue with your scandir() and unset() combination. As you've discovered scandir() basically gives you everything that a dir or ls would on the command line. Using unset() to remove specific files is problematic because you have to maintain a hardcoded list of files. However, unset() also leaves holes in your array, the count changes but the original indices do not. This may be why you are using $folderamount + 10 in your loop. Take a look at this Stack Overflow question for more discussion of the problem.
Rebase array keys after unsetting elements
I recommend you read the PHP manual page on the glob() function as it will greatly simplify getting the contents of a directory. In particular take a look at the GLOB_ONLYDIR flag.
https://www.php.net/manual/en/function.glob.php
Lastly, don't increment your loop counter at the beginning of the loop when using the counter to read elements from an array. Take a look at the PHP manual page for foreach loops for a neater way to iterate over an array.
https://www.php.net/manual/en/control-structures.foreach.php

How create recursively ZIP file, from array which contains total directory paths WITHOUT the name of the pdfs inside

I have a directory with name 2019. I want to create a ZIP file which contains all the pdf files inside the folders 01-03. In a for loop, I fill an array with all the paths of the directories who are not empty. Now I don't know how to open a stream or something else to put the array values inside in a for loop and recursively add all pdfs under each subfolder path inside it. Any idea guys?
for ($i = 1; $i < 4; $i++) {
// for the 3 months of this year
$absolutepath = "$year_path/0$i";
if (file_exists($absolutepath) && glob($absolutepath . "/*")) {
// check if path/year/month exists
// check if folder contains any files
// store specific full paths inside array for use
array_push($path_array, $absolutepath);
}
}
// how can i put here $path_array into a function to create zip file which contains all the pdfs under each subfolder path of the $path_array ???
It looks like you are creating the string wrong. You have to concatenate the variables outside of the string for the path separator with the leading zero. I think it should be:
$absolutepath = $year_path + "/0" + $i;

glob() function only returns empty array in php

I've been trying to make a simple website that lets you specify a directory, and embeds a player for each mp3 in whatever directory the user specifies. The problem is that no matter how I enter the directory name, glob() does not return any files. I've tried this with local folders, server directories, and the same folder as the php file.
'directoryPath' is the name of the text box where the user enters, you guessed it, the directory path. The 'echo $files' statement displays nothing onscreen. The 'echo "test"' statement DOES run, but the 'echo "hello"' statement in the loop does not execute.
Any help is appreciated!
if (!empty($_POST['directoryPath']))
{
$path = ($_POST['directoryPath']);
$files = glob("$path/{*.mp3}", GLOB_BRACE);
echo $files[0];
echo "test";
foreach($files as $i)
{
echo "hello";
echo $files[$i];
?>
<embed src=<?php $files[$i]; ?> width=256 height=32 autostart=false repeat=false loop=false></embed><?php echo $files[$i] ?></p>
<?php;
}
unset($i);
}
Validate the input first:
$path = realpath($_POST['directoryPath']);
if (!is_dir($path)) {
throw new Exception('Invalid path.');
}
...
Additionally check the return value glob returns false on error. Check for that condition (and ensure you are not using one of those systems that even return false when there are no files found).
I hope this is helpful. And yes, check your error log and enable error logging. This is how you can see what is going wrong.
Also see the following related function for a usage-example and syntax of GLOB_BRACE:
Running glob() from an included script returns empty array
One one tool I find very useful in helping debug variables in PHP is var_dump(). It's a function that provides you with information about a variable's type, it's contents, and any useful metadata it can attain from that variable. This would be a very useful tool for you here, because you'll quickly realize what you have in the variable $i is not at all what you expect.
$files = glob("$path/{*.mp3}", GLOB_BRACE);
foreach ($files as $i) {
var_dump($i);
}
/* Here's a hint, $i is not an index to the $files array.
So $files[$i] makes no sense. $i is actually the value not the key.*/
foreach ($files as $key => $value) { // very different from
// $key is the key to the current element of $files we're iterating over
// $value is the value of the current element we're iterating over
}
So in your code $i is the value not the key. See http://php.net/foreach for more information on how the construct works.
Also, what should be noted here is that you are using a relative path, whereas glob will return an absolute path. By relative this means your searching relative to the CWD (Current Working Directory) of your PHP script. To see wha that is you can use the following code.
var_dump(real_path('.'));
// similarly ...
var_dump(getcwd());

PHP readir results - trying to sort by date created and also get rid of "." and ".."

I have a double question. Part one: I've pulled a nice list of pdf files from a directory and have appended a file called download.php to the "href" link so the pdf files don't try to open as a web page (they do save/save as instead). Trouble is I need to order the pdf files/links by date created. I've tried lots of variations but nothing seems to work! Script below. I'd also like to get rid of the "." and ".." directory dots! Any ideas on how to achieve all of that. Individually, these problems have been solved before, but not with my appended download.php scenario :)
<?php
$dir="../uploads2"; // Directory where files are stored
if ($dir_list = opendir($dir))
{
while(($filename = readdir($dir_list)) !== false)
{
?>
<p><a href="http://www.duncton.org/download.php?file=login/uploads2/<?php echo $filename; ?>"><?php echo $filename;
?></a></p>
<?php
}
closedir($dir_list);
}
?>
While you can filter them out*, the . and .. handles always come first. So you could just cut them away. In particular if you use the simpler scandir() method:
foreach (array_slice(scandir($dir), 2) as $filename) {
One could also use glob("dir/*") which skips dotfiles implicitly. As it returns the full path sorting by ctime then becomes easier as well:
$files = glob("dir/*");
// make filename->ctime mapping
$files = array_combine($files, array_map("filectime", $files));
// sorts filename list
arsort($files);
$files = array_keys($files);

List directory filenames by file word count

I'd like to,
Check the word count for a folder full of text files.
Output a list of the files arranged by word count in the format - FILENAME is WORDCOUNT
I know str_word_count is used to get individual wordcounts for files but I'm not sure how to rearrange the output.
Thanks in advance.
Adapted from here.
<?php
$files = array();
$it = new DirectoryIterator("/tmp");
$it->rewind();
while ($it->valid()) {
$count = str_word_count(file_get_contents($it->getFilename()));
$files[sprintf("%010d", $count) . $it->getFilename()] =
array($count, $it->getFilename());
$it->next();
}
ksort($files);
foreach ($files as $tup) {
echo sprintf("%s is %d\n", $tup[1], $tup[0]);
}
EDIT It would be more elegant to have $file's key be the file name and $file's value be the word count and then sort by value.
I don't use php but I would
create array to hold filename and
wordcount
read through the folder full of text
files and for each save the filename
and wordcount to the array
sort the array by wordcount
output the array
To store the information (#2) I would put the information into a 2D array. There is more information about 2D arrays here at Free PHP Tutorial. Thus array[0][0] would equal the name of the first file and array0 would be the wordcount. array1[0] and array1 would be the for the next file.
To sort the array (#3) you can use the tutorial firsttube.com.
The to output I would do a loop through the array and output the first and second location.
for ($i = 0; $i < sizeof($array); ++$i) {
print the filename ($array[$i][0]) and wordcount ($array[$i][1])
}
If you would like to keep the iterator-style approach (yet still do essentially the same as Artefacto's answer) then something like the following would suffice.
$dir_it = new FilesystemIterator("/tmp");
// Build array iterator with word counts
$arr_it = new ArrayIterator();
foreach ($dir_it as $fileinfo) {
// Skip non-files
if ( ! $fileinfo->isFile()) continue;
$fileinfo->word_count = str_word_count(file_get_contents($fileinfo->getPathname()));
$arr_it->append($fileinfo);
}
// Sort by word count descending
$arr_it->uasort(function($a, $b){
return $b->word_count - $a->word_count;
});
// Display sorted files and their word counts
foreach ($arr_it as $fileinfo) {
printf("%10d %s\n", $fileinfo->word_count, $fileinfo->getFilename());
}
Aside: If the files are particularly large (read: loading each one entirely into memory just to count the words is too much) then you could loop over the file line-by-line (or byte-by-byte if you really wanted to) with the SplFileObject.

Categories