PHP Directories - php

Can someone please xplain this code. Im reading larry ullmans book on php and i dont get this part. Thanks in advance!!
$search_dir = '.';
$contents = scandir($search_dir);
print '<h2>Directories</h2>
<ul>';
foreach ($contents as $item) {
if ( (is_dir($search_dir . '/' . $item)) AND (substr($item, 0, 1) != '.') ) {
print "<li>$item</li>\n";
}
}
print '</ul>';

It shows you list of all directories in current directory

I'll repost your code with comments to exaplain what each line does.
$search_dir = '.'; //Set the directory to search. "." means the current one.
$contents = scandir($search_dir); //scan the directory and return its results into $contents
print '<h2>Directories</h2>
<ul>';
foreach($contents as $item) { //Iterate through the array and for each item...
//If the item is a directory AND it doesn't start with a . (which means the current one)...
if ((is_dir($search_dir.'/'.$item)) AND(substr($item, 0, 1) != '.')) {
print "<li>$item</li>\n"; //Print it
}
}
print '</ul>';
In short, it prints out an output of the directories inside the directory the script is running in.

Related

php loop through files in subfolders in folder and get file paths

Im really new to PHP i searched google to find a correct script that loops through all subfolders in a folder and get all files path in that subfolder
<?php
$di = new RecursiveDirectoryIterator('posts');
foreach (new RecursiveIteratorIterator($di) as $filename => $file) {
echo $filename. '<br/>';
}
?>
So i have folder 'posts' in which i have subfolder 'post001' in which i have two files
controls.png
text.txt
And the code above echos this
posts\.
posts\..
posts\post001\.
posts\post001\..
posts\post001\controls.png
posts\post001\text.txt
But i want to echo only the file paths inside these subfolders like this
posts\post001\controls.png
posts\post001\text.txt
The whole point of this is that i want to dynamically create divs for each subfolder and inside this div i put img with src and some h3 and p html tags with text equal to the .txt file so is this proper way of doing that and how to remake my php script so that i get just the file paths
So I can see the answers and they are all correct but now my point was that i need something like that
foreach( glob( 'posts/*/*' ) as $filePath ){
//create div with javascript
foreach( glob( 'posts/$filePath/*' ) as $file ){
//append img and h3 and p html tags to the div via javascript
}
//append the created div somewhere in the html again via javascript
}
So whats the correct syntax of doing these two foreach loops in php im really getting the basics now
See if this works :)
$di = new RecursiveDirectoryIterator('posts');
foreach (new RecursiveIteratorIterator($di) as $filename => $file) {
if ((substr($file, -1) != '.') && (substr($file, -2) != '..')) {
echo $file . '<br/>';
}
}
<h1>Directory Listing</h1>
<?php
/**
* Recursive function to append the full path of all files in a
* given directory $dirpath to an array $context
*/
function getFilelist($dirpath, &$context){
$fileArray = scandir($dirpath);
if (count($fileArray) > 2) {
/* Remove the . (current directory) and .. (parent directory) */
array_shift($fileArray);
array_shift($fileArray);
foreach ($fileArray as $f) {
$full_path = $dirpath . DIRECTORY_SEPARATOR . $f;
/* If the file is a directory, call the function recursively */
if (is_dir($full_path)) {
getFilelist($full_path, $context);
} else {
/* else, append the full path of the file to the context array */
$context[] = $full_path;
}
}
}
}
/* $d is the root directory that you want to list */
$d = '/Users/Shared';
/* Allocate the array to store of file paths of all children */
$result = array();
getFilelist($d, $result);
$display_length = false;
if ($display_length) {
echo 'length = ' . count($result) . '<br>';
}
function FormatArrayAsUnorderedList($context) {
$ul = '<ul>';
foreach ($context as $c) {
$ul .= '<li>' . $c . '</li>';
}
$ul .= '</ul>';
return $ul;
}
$html_list = FormatArrayAsUnorderedList($result);
echo $html_list;
?>
Take a look at this:
<?php
$filename[] = 'posts\.';
$filename[] = 'posts\..';
$filename[] = 'posts\post001\.';
$filename[] = 'posts\post001\..';
$filename[] = 'posts\post001\controls.png';
$filename[] = 'posts\post001\text.txt';
foreach ($filename as $file) {
if (substr($file, -4, 1) === ".") {
echo $file."<br>";
}
}
?>
Result:
posts\post001\controls.png
posts\post001\text.txt
What this does is checking if the 4th last digit is a dot. If so, its an extension of three letters and it should be a file. You could also check for specific extensions.
$ext = substr($file, -4, 4);
if ($ext === ".gif" || $ext === ".jpg" || $ext === ".png" || $ext === ".txt") {
echo $file."<br>";
}

How to list all files in folders and sub-folders using scandir and display them as an option in select?

I have a piece of code that I would like to modify to list all files in folders and sub-folders in the current path. I have found several possible solutions. I tried to implement them actually, but nothing seemed to work so I am not sure if they are actually working or not or it was just me implemented them wrong. Either way this is my current code:
<?php
$currentdir = 'C:/xampp/htdocs/test/'; //change to your directory
$dir = opendir($currentdir);
echo '<select name="workout">';
$file = preg_grep('/^([^.])/', scandir($dir));
while($file = readdir($dir))
{
if ($file != "." && $file != "..") {
echo "<option value='$file'>$file</option>";
}
else {
continue;
}
}
echo '</select>';
closedir($dir);
?>
Currently this code shows results:
$currentdir
Option1
Option2
Option3
SUB-FOLDER1
SUB-FOLDER2
Can someone help me and show me how to write/rewrite the code using existing one to display files from folders and other sub-folders to look something like this:
$currentdir
Option1
Option2
Option3
SUB-FOLDER1
Option1
Option2
Option3
SUB-FOLDER2
Option1
Option2
Option3
I became really desperate for a solution and thank you all in advance.
While the other answers are fine and correct, allow me to add my solution as well:
function dirToOptions($path = __DIR__, $level = 0) {
$items = scandir($path);
foreach($items as $item) {
// ignore items strating with a dot (= hidden or nav)
if (strpos($item, '.') === 0) {
continue;
}
$fullPath = $path . DIRECTORY_SEPARATOR . $item;
// add some whitespace to better mimic the file structure
$item = str_repeat(' ', $level * 3) . $item;
// file
if (is_file($fullPath)) {
echo "<option>$item</option>";
}
// dir
else if (is_dir($fullPath)) {
// immediatly close the optgroup to prevent (invalid) nested optgroups
echo "<optgroup label='$item'></optgroup>";
// recursive call to self to add the subitems
dirToOptions($fullPath, $level + 1);
}
}
}
echo '<select>';
dirToOptions();
echo '</select>';
It uses a recursive call to fetch the subitems. Note that I added some whitespace before each item to better mimic the file structure. Also I closed the optgroup immediatly, to prevent ending up with nested optgroup elements, which is invalid HTML.
Find all the files and folders under a specified directory.
function scanDirAndSubdir($dir, &$out = []) {
$sun = scandir($dir);
foreach ($sun as $a => $filename) {
$way = realpath($dir . DIRECTORY_SEPARATOR . $filename);
if (!is_dir($way)) {
$out[] = $way;
} else if ($filename != "." && $filename != "..") {
scanDirAndSubdir($way, $out);
$out[] = $way;
}
}
return $out;
}
var_dump(scanDirAndSubdir('C:/xampp/htdocs/test/'));
Sample :
array (size=4)
0 => string 'C:/xampp/htdocs/test/text1.txt' (length=30)
1 => string 'C:/xampp/htdocs/test/text1.txt' (length=30)
2 => string 'C:/xampp/htdocs/test/subfolder1/text8.txt' (length=41)
3 => string 'C:/xampp/htdocs/test/subfolder4/text9.txt' (length=41)
Use DirectoryIterator for looking into folder here is my approch
$di = new DirectoryIterator("/dir");
foreach($di as $dir){
if ($dir->isDot()) continue;
echo "<option value='", $dir->getFilename(), "'>", $dir->getFilename(), "</option>";
}
anyway for looking into sub directories as well
$ri = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($path), RecursiveIteratorIterator::SELF_FIRST);
foreach($ri as $dir){
if ($dir->isDot()) continue;
echo "<option value='", $dir->getFilename(), "'>", $dir->getFilename(), "</option>";
}
In case you don't want to use above statement then this another alternative:
<?php
function listdir($currentdir){
$dir = opendir($currentdir);
$file = readdir($dir);
echo "<optgroup label='$currentdir'>";
do {
if (is_dir($currentdir."/".$file) && $file != "." && $file != ".."){
listdir($currentdir."/".$file);
echo $currentdir."/".$file;
} else if($file != "." && $file != "..") {
echo "<option value='$file'>$file</option>";
} else {
continue;
}
} while($file = readdir($dir));
echo "</optgroup>";
closedir($dir);
}
echo '<select name="workout">';
listdir('/var/www'); //change to your directory
echo '</select>';
?>

PHP recursive directory menu (different approaches)

I'm trying to create a PHP menu which displays the directories and files in each directory in a list, with links to each file in those directories (but not links to the directories themselves). The directories are numerical as years '2013', '2014', etc., and the files in these directories are PDFs.
In essence:
--- 2013 (not linked)
--------------- 01.pdf (linked)
--------------- 02.pdf (linked)
--------------- 03.pdf (linked)
--- 2014 (not linked)
--------------- 04.pdf (linked)
--------------- 05.pdf (linked)
--------------- 06.pdf (linked)
Currently, my code looks like this:
<?php
function read_dir_content($parent_dir, $depth = 0){
if ($handle = opendir($parent_dir))
{
while (false !== ($file = readdir($handle)))
{
if(in_array($file, array('.', '..'))) continue;
if( is_dir($parent_dir . "/" . $file) ){
$str_result .= "<li>" . read_dir_content($parent_dir . "/" . $file, $depth++) . "</li>";
}
$str_result .= "<li><a href='prs/{$file}'>{$file}</a></li>";
}
closedir($handle);
}
$str_result .= "</ul>";
return $str_result;
}
echo "<ul>".read_dir_content("prs/")."</ul>";
?>
However, this creates a complete mess when processed. (Unfortunately I cannot post an image as I am a new user, but if it's not too taboo, I will provide a sneaky link to it: http://i.stack.imgur.com/gmIFz.png)
My questions/requests for help on:
1. Why is the order reversed alphanumerically, i.e. why is 2013 at the bottom of the list and 2014 at the top?
2. How can I remove the links for the directories while keeping the links for the PDFs?
3. I'm confused over why there are empty list items at the end of each directory's list and why they are not logically/consistently spaced, i.e. why are the 01, 02, 03 PDFs not subordinate to the 2013 (see 'in essence' spacing above)?
N.B. I am new to programming and PHP, so please bear in mind that my obvious mistake/s might be very simple. Sorry in advance if they are.
edit: what would also be a massive bonus would be to get rid of the ".pdf"s on the end of the filenames, but that is probably an entirely different question/matter.
PHP5 has class called RecursiveDirectoryIterator
This code :
Sorts the list as you want (2013 first then 2014)
Does not show the links to the directories
Solves the formatting troubles
BONUS: removes the pdf extension
..
$myLinks = array();
$dirIterator = new RecursiveDirectoryIterator($parent_dir);
//iterates main prs directory
foreach ($dirIterator as $file) {
// If its a directory, it will iterate it's children (except if it's . or ..)
if ($file->isDir() && $file->getFilename() != '.' && $file->getFilename() != '..') {
$dir = new RecursiveDirectoryIterator($file->getRealPath());
$myLinks[$file->getFilename()] = array();
foreach ($dir as $subFile) {
//If it finds a file whose extension is pdf
if ($subFile->isFile() && $subFile->getExtension() == 'pdf') {
// Gets its filename and removes extension
$fname = str_replace('.pdf', '', $subFile->getFilename());
// adds the file information to an array
$myLinks[$file->getFilename()][$fname] = "prs/{$file->getFilename()}/{$subFile->getFilename()}";
}
}
}
}
//Sort our array alphabetically (and numerically) and recursively
ksort_recursive($myLinks);
function ksort_recursive(&$array)
{
if (!is_array($array)) return;
ksort($array);
foreach ($array as $k=>$v) {
ksort_recursive($array[$k]);
}
}
// now we print our links as a unordered list
print '<ul>';
foreach ($myLinks as $year => $val) {
print "<li>$year";
foreach ($val as $name => $link) {
print "<li><a href='$link'>$name</a></li>";
}
print '</li>';
}
print '</ul>';
First off I see this line in there
$str_result .= "</ul>";
but I don't see an opening ul tag. This is probably the source of the crazy looking result.
1) I would use scandir instead of readdir as it would let you set the sort order.
2,3) Get rid of $str_result .= "</ul>"; and try something like this in your inside your while loop to remove the dir links and get the order right: (NOTE: I have not run this)
if( ! in_array($file, array('.', '..')) ) {
if( is_dir($parent_dir . "/" . $file) ){
$str_result .= "<li>{$file}</li>";
$str_result .= "<ul>";
$str_result .= "<li>" . read_dir_content($parent_dir . "/" . $file, $depth++) . "</li>";
$str_result .= "</ul>";
} else {
$str_result .= "<li><a href='prs/{$file}'>{$file}</a></li>";
}
}

Print out questions in sequential order in PHP

Problem:
I have a zip file that contains 13 xml files. Each file, except for the first one, contain a quiz question and several answers. When I upload the file to the below script it prints out the questions and the answers correctly, but NOT in order. The order of questions randomly shift each time I upload the zip-file.
Question:
Is there a way I can utilize the file names to tell the script to print out the questions in sequential order every time?
Zip-file contain:
imsmanifest.xml
item101008.xml
item101009.xml
item101010.xml
item101011.xml
item101012.xml
item101013.xml
item101014.xml
item101015.xml
item101016.xml
item101017.xml
item101018.xml
item101019.xml
PHP-script (warning, long script):
<?php
//Initialize counter
$i = 0;
//Go through each file
while (($file = readdir($dh)) !== false)
{
//Skipt the first loop
if ($i > 1)
{
//Ignore misc file
if ($file != 'imsmanifest.xml')
{
//Create new DOM document
$dom= new DOMDocument();
//Load XML file
$dom->load('uploads/' . $file);
//Do not preserve white space
$dom->preserveWhiteSpace = false;
//Check if correct answers should be displayed
if (isset($_POST['XMLAnswers']))
{
//Get correct answer
$correct = $dom->getElementsByTagName( "correctResponse" )->item(0)->nodeValue;
//Get question
$questions = $dom->getElementsByTagName('p')->item(0)->nodeValue;
//Print out question
echo '<h4>' . htmlspecialchars($questions) . '</h4>' . "\n";
//Get answers
$domTable = $dom->getElementsByTagName("simpleChoice");
//Loop through each answer
foreach ($domTable as $answers)
{
//Delete potential unnecessary tags
$pattern = array(
'<p xmlns="http://www.imsglobal.org/xsd/imsqti_v2p1">',
'</p>'
);
//Check if answer is correct one
if ($correct == $answers->getAttribute('identifier'))
{
//Print out correct answer
echo '<span style="color:red;">' . utf8_decode(str_replace($pattern, '', innerHTML($answers))) . '</span><br />' . "\n";
}
else
{
//Print out answer
echo utf8_decode(str_replace($pattern, '', innerHTML($answers))) . '<br />' . "\n";
}
}
}
}
}
//Increment counter
$i++;
}
?>
Rather than using opendir/readdir, use scandir. See http://www.php.net/manual/en/function.scandir.php. scandir returns you a sorted array of files in the directory. You should be able to drop this in and have your code work with minimal changes, other than replacing the outer while readdir loop with:
$files = scandir($dir);
foreach ($files as $file) {
//your current code
}

php count files from multiple folders and echo total

I have a php code that will display the amount of files that i have in a folder.
Code: This will echo this on my page, "There are a total of 119 Articles"
$directory = "../health/";
if (glob($directory . "*.php") != false) /* change php to the file you require either html php jpg png. */ {
$filecount = count(glob($directory . "*.php")); /* change php to the file you require either html php jpg png. */
echo "<p>There are a total of";
echo " $filecount ";
echo "Articles</p>";
} else {
echo 0;
}
Question:
I am wanting to count the files from 27 or more folders and echo the total amount of files.
Is there away i can add a list of folders to open such as:
$directory = "../health/","../food/","../sport/";
then it will count all the files and display the total "There are a total of 394 Articles"
Thanks
Yes you can:
glob('../{health,food,sport}/*.php', GLOB_BRACE);
Undoubtedly, this is less efficient than clover's answer:
$count = 0;
$dirs = array("../health/","../food/","../sport/");
foreach($dirs as $dir){
if($files = glob($dir."*.php")){
$count += count($files);
}
}
echo "There are a total of $count Articles";
A simple answer is to just use an array and a loop. It is something you could have figured out yourself.
$directories = array('../health/', '../food/', '../sport/');
$count = 0;
foreach ($directories as $dir) {
$files = glob("{$dir}*.php") ?: array();
$count += count($files);
}
echo "<p>There are a total of {$count} articles</p>";
But #clover's answer is better.
As usual, it's often much better to divide your problem. E.g.:
Obtain the files (See glob).
Count the files of a glob result (Write a function that takes care of two the FALSE and Array cases.).
Do the output (don't do the output inside the other code, do it at the end, use variables (as you already do, just separate the output)).
Some Example Code:
/**
* #param array|FALSE $mixed
* #return int
* #throws InvalidArgumentException
*/
function array_count($mixed) {
if (false === $mixed) {
return 0;
}
if (!is_array($mixed)) {
throw new InvalidArgumentException('Parameter must be FALSE or an array.');
}
return count($mixed);
}
$directories = array("health", "food", "string");
$pattern = sprintf('../{%s}/*.php', implode(',', $directories));
$files = glob($pattern, GLOB_BRACE);
$filecount = array_count($files);
echo "<p>There are a total of ", $filecount, " Article(s)</p>";
You could use the opendir command explained here:
http://www.php.net/manual/en/function.opendir.php
combined with the example shown on previous link:
<?php
$dir = "/etc/php5/";
// Open a known directory, and proceed to read its contents
if (is_dir($dir)) {
if ($dh = opendir($dir)) {
while (($file = readdir($dh)) !== false) {
echo "filename: $file : filetype: " . filetype($dir . $file) . "\n";
}
closedir($dh);
}
}
?>
Basically opening the folder you first go through and in a loop count every singel item that is not a folder.
Edit:
Seems like someone has given a simpler solution than this.

Categories