This is my code:
<?php
function recursive($directory){
$nr = 0;
$files = scandir($directory);
foreach($files as $file){
if($file == '.' || $file == '..') continue;
if(is_dir($file)){
echo $file.'<br>';
continue;
}
echo $file.' ----------<br>';
}
}
recursive('.');
?>
Basically I want the code at the bottom of the loop to be skipped until they are no more files in the directory.
How I want it to look:
How it looks:
A different take on your code but have you looked at the recursiveIterator family of classes? It's part of the php core and is pretty powerful.
$folder='c:/temp';
foreach( new RecursiveIteratorIterator( new RecursiveDirectoryIterator( $folder, RecursiveDirectoryIterator::KEY_AS_PATHNAME ), RecursiveIteratorIterator::CHILD_FIRST ) as $file => $info ) {
if( $info->isFile() && $info->isReadable() && $info->isWritable() ){
echo $info->getFilename().'-------<br />';
} elseif( $info->isDir() ){
echo $info->getPath().'<br />';
}
}
I think you first need to list the directories, then the files. You can do that by changing a bit your function and running it twice:
function recursive($directory, $type){
$nr = 0;
$files = scandir($directory);
foreach($files as $file){
if($file == '.' || $file == '..') continue;
if(is_dir($file) && $type == 'dir'){
echo $file.'<br>';
} else if(!is_dir($file) && $type == 'file'){
echo $file.' ----------<br>';
}
}
}
recursive('.', 'dir');
recursive('.', 'file');
(By the way, although it's called "recursive", it doesn't do recursion)
Like this?
echo $file.'<br>';
if(is_dir($file) === false){
echo $file.' ----------<br>';
}
Related
i want to list all directory, sub-directory and files using php.
i have tried following code. it returns all the directory, sub directory and files but it's not showing in correct order.
for ex:default order is 1dir, 2dir, 7dir, 8dir while in browser it shows 1dir, 8dir, 7dir, 2dir which is not correct.
code:
function createDir($path = '.')
{
if ($handle = opendir($path))
{
echo "<ul>";
while (false !== ($file = readdir($handle)))
{
if (is_dir($path.$file) && $file != '.' && $file !='..') {
printSubDir($file, $path);
}
else if ($file != '.' && $file !='..'){
$allowed = array('pdf','doc','docx','xls','xlsx','jpg','png','gif','mp4','avi','3gp','flv','mov','PDF','DOC','DOCX','XLS','XLSX','JPG','PNG','GIF','MP4','AVI','3GP','FLV','MOV','html','HTML','css','CSS','js','JS');
$ext = pathinfo($file, PATHINFO_EXTENSION);
if(in_array($ext,$allowed) ) {
$queue[] = $file;
}
}
}
printQueue($queue, $path);
echo "</ul>";
}
}
function printQueue($queue, $path)
{
sort($queue);
foreach ($queue as $file)
{
//printFile($file, $path);
}
}
function printFile($file, $path) {
echo "<li><a href=\"".$path.$file."\" target='_blank'>$file</a></li>";
}
function printSubDir($dir, $path)
{
echo "<li><span class=\"toggle\">$dir</span>";
createDir($path.$dir."/");
echo "</li>";
}
createDir($path);
?>
need help to fix the code and display the direcotry , subdirectory and files in correct order.
I'm having the same problem during listing a directory files. But I have used DirectoryLister
This code is very useful. You can list out your files easily.
You can implement it by following steps.
Download and extract Directory Lister
Copy resources/default.config.php to resources/config.php
Upload index.php and the resources folder to the folder you want listed
Upload additional files to the same directory as index.php
I hope this might help you
You can start by looping the array and printing each directory:
public function dirtree($dir, $regex='', $ignoreEmpty=false) {
if (!$dir instanceof DirectoryIterator) {
$dir = new DirectoryIterator((string)$dir);
}
$dirs = array();
$files = array();
foreach ($dir as $node) {
if ($node->isDir() && !$node->isDot()) {
// print_r($node);
$tree = dirtree($node->getPathname(), $ignoreEmpty);
// print"<pre>";print_r($tree);
if (!$ignoreEmpty || count($tree)) {
$dirs[$node->getFilename()] = $tree;
}
} elseif ($node->isFile()) {
$name = $node->getFilename();
//if ('' == $regex || preg_match($regex, $name)) {
$files[] = $name;
}
}
asort($dirs);
sort($files);
return array_merge($files, $dirs);
}
Use like this:
$fileslist = dirtree('root');
echo "<pre style='font-size:15px'>";
print_r($fileslist);
I am writing a simple fishing game in PHP. I have a snippet of code that's printing all of the image files in my /img directory, but it's also outputting .DS_Store. I want to exclude that file, maybe using glob(), but I don't know how. I've googled this for hours with no luck.
$files = scandir('img');
if ($files !== false) {
foreach($files as $f) {
if ($f == '..' || $f == '.') continue;
echo '<li class="fish_pic"><img src="img/'.$f.'" alt="'.$f.'" title="" class="fish"></li>'."\n";
}
}
How can I exclude .DS_Store?
Just add an if rule.
if ($f == '..' || $f == '.' || $f == '.DS_Store') continue;
Alternatively, you could use an array and in_array() method.
$filesToSkip = array('.', '..', '.DS_Store', 'other_file_to_skip');
$files = scandir('img');
if ($files !== false) {
foreach($files as $f) {
if (in_array($f, $filesToSkip)) continue;
echo '<li class="fish_pic"><img src="img/'.$f.'" alt="'.$f.'" title="" class="fish"> </li>'."\n";
}
}
$files = scandir('img');
if ($files !== false) {
foreach($files as $f) {
if ($f == '..' || $f == '.' || substr($f, -strlen(".DS_Store")) === ".DS_Store") continue;
echo '<li class="fish_pic"><img src="img/'.$f.'" alt="'.$f.'" title="" class="fish"></li>'."\n";
}
}
I have a bit of PHP used to pulled a list of files from my image directory - it's used in a form to select where an uploaded image will be saved. Below is the code:
$files = array_map("htmlspecialchars", scandir("../images"));
foreach ($files as $file) {
$filelist .= sprintf('<option value="%s">%s</option>' . PHP_EOL, $file, $file );
}
It works fine but shows all files and folders in 'images', does someone know a way to modify this code so that it only shows folder names found in the 'images' folder, not any other files.
Thanks
The easiest and quickest will be glob with GLOB_ONLYDIR flag:
foreach(glob('../images/*', GLOB_ONLYDIR) as $dir) {
$dirname = basename($dir);
}
Function is_dir() is the solution :
foreach ($files as $file) {
if(is_dir($file) and $file != "." && $file != "..") $filelist .= sprintf('<option value="%s">%s</option>' . PHP_EOL, $file, $file );
}
The is_dir() function requires an absolute path to the item that it is checking.
$base_dir = get_home_path() . '/downloads';
//get_home_path() is a wordpress function
$sub_dirs = array();
$dir_to_check = scandir($dir);
foreach ($dir_to_check as $item){
if ($item != '..' && $item != '.' && is_dir($base_dir . "/" . $item)){
array_push($sub_dirs, $item);
}
}
You could just use your array_map function combined with glob
$folders = array_map(function($dir) {
return basename($dir);
}, glob('../images/*', GLOB_ONLYDIR));
Yes, I copied a part of it of dev-null-dweller, but I find my solution a bit more re-useable.
I try this
<?php
$dir = "../";
$a = array_map("htmlspecialchars", scandir($dir));
$no = 0; foreach ($a as $file) {
if ( strpos($file, ".") == null && $file !== "." && $file !== ".." ) {
$filelist[$no] = $file; $no ++;
}
}
print_r($filelist);
?>
$dir = '/master/files';
$files = scandir($dir);
foreach($files as $file){
if(($file != '.') && ($file != '..')){
if(is_dir($dir.'/'.$file)){
echo '<li class="folder">'.$file.'</li>';
}else{
echo '<li class="file">'.$file.'</li>';
}
}
}
From the script above, I get result:
images (folder)
index.html
javascript (folder)
style.css
How to sort the folder first and then files?
Try this :
$dir = '/master/files';
$directories = array();
$files_list = array();
$files = scandir($dir);
foreach($files as $file){
if(($file != '.') && ($file != '..')){
if(is_dir($dir.'/'.$file)){
$directories[] = $file;
}else{
$files_list[] = $file;
}
}
}
foreach($directories as $directory){
echo '<li class="folder">'.$directory.'</li>';
}
foreach($files_list as $file_list){
echo '<li class="file">'.$file_list.'</li>';
}
You don't need to make 2 loops, you can do the job with this piece of code:
<?php
function scandirSorted($path) {
$sortedData = array();
foreach(scandir($path) as $file) {
// Skip the . and .. folder
if($file == '.' || $file == '..')
continue;
if(is_file($path . $file)) {
// Add entry at the end of the array
array_push($sortedData, '<li class="folder">' . $file . '</li>');
} else {
// Add entry at the begin of the array
array_unshift($sortedData, '<li class="file">' . $file . '</li>');
}
}
return $sortedData;
}
?>
This function will return the list of entries of your path, folders first, then files.
Modifying your code as little as possible:
$folder_list = "";
$file_list = "";
$dir = '/master/files';
$files = scandir($dir);
foreach($files as $file){
if(($file != '.') && ($file != '..')){
if(is_dir($dir.'/'.$file)){
$folder_list .= '<li class="folder">'.$file.'</li>';
}else{
$file_list .= '<li class="file">'.$file.'</li>';
}
}
}
print $folder_list;
print $file_list;
This only loops through everything once, rather than requiring multiple passes.
I have a solution for N deep recursive directory scan:
function scanRecursively($dir = "/") {
$scan = array_diff(scandir($dir), array('.', '..'));
$tree = array();
$queue = array();
foreach ( $scan as $item )
if ( is_file($item) ) $queue[] = $item;
else $tree[] = scanRecursively($dir . '/' . $item);
return array_merge($tree, $queue);
}
Store the output in 2 arrays, then iterate through the arrays to output them in the right order.
$dir = '/master/files';
$contents = scandir($dir);
// create blank arrays to store folders and files
$folders = $files = array();
foreach ($contents as $file) {
if (($file != '.') && ($file != '..')) {
if (is_dir($dir.'/'.$file)) {
// add to folders array
$folders[] = $file;
} else {
// add to files array
$files[] = $file;
}
}
}
// output folders
foreach ($folders as $folder) {
echo '<li class="folder">' . $folder . '</li>';
}
// output files
foreach ($files as $file) {
echo '<li class="file">' . $file . '</li>';
}
Being a CodeIgniter lover, I have in fact modified the core directory_helper from that to include the ability to have certain files exempt from the scanning in addition to setting the depth and choosing if hidden files should be included.
All credit goes to the original authors of CI. I simply added to it
with the exempt array and building in the sorting.
It uses ksort to order the folders, as the folder name is set as the key and natsort to order the files inside each folder.
The only thing you may need to do is define what the DIRECTORY_SEPARATOR is for your environment but I don't think you will need to modify much else.
function directory_map($source_dir, $directory_depth = 0, $hidden = FALSE, $exempt = array())
{
if ($fp = #opendir($source_dir))
{
$folddata = array();
$filedata = array();
$new_depth = $directory_depth - 1;
$source_dir = rtrim($source_dir, DIRECTORY_SEPARATOR).DIRECTORY_SEPARATOR;
while (FALSE !== ($file = readdir($fp)))
{
// Remove '.', '..', and hidden files [optional]
if ($file === '.' OR $file === '..' OR ($hidden === FALSE && $file[0] === '.'))
{
continue;
}
is_dir($source_dir.$file) && $file .= DIRECTORY_SEPARATOR;
if (($directory_depth < 1 OR $new_depth > 0) && is_dir($source_dir.$file))
{
$folddata[$file] = directory_map($source_dir.$file, $new_depth, $hidden, $exempt);
}
elseif(empty($exempt) || !empty($exempt) && !in_array($file, $exempt))
{
$filedata[] = $file;
}
}
!empty($folddata) ? ksort($folddata) : false;
!empty($filedata) ? natsort($filedata) : false;
closedir($fp);
return array_merge($folddata, $filedata);
}
return FALSE;
}
Usage example would be:
$filelist = directory_map('full_server_path');
As mentioned above, it will set the folder name as the key for the child array, so you can expect something along the lines of the following:
Array(
[documents/] => Array(
[0] => 'document_a.pdf',
[1] => 'document_b.pdf'
),
[images/] => Array(
[tn/] = Array(
[0] => 'picture_a.jpg',
[1] => 'picture_b.jpg'
),
[0] => 'picture_a.jpg',
[1] => 'picture_b.jpg'
),
[0] => 'file_a.jpg',
[1] => 'file_b.jpg'
);
Just keep in mind that the exempt will be applied to all folders. This is handy if you want to skip out a index.html file or other file that is used in the directories you don't want included.
Try
<?php
$path = $_SERVER['DOCUMENT_ROOT'];
chdir ($path);
$dir = array_diff (scandir ('.'), array ('.', '..', '.DS_Store', 'Thumbs.db'));
usort ($dir, create_function ('$a,$b', '
return is_dir ($a)
? (is_dir ($b) ? strnatcasecmp ($a, $b) : -1)
: (is_dir ($b) ? 1 : (
strcasecmp (pathinfo ($a, PATHINFO_EXTENSION), pathinfo ($b, PATHINFO_EXTENSION)) == 0
? strnatcasecmp ($a, $b)
: strcasecmp (pathinfo ($a, PATHINFO_EXTENSION), pathinfo ($b, PATHINFO_EXTENSION))
))
;
'));
header ('content-type: text/plain');
print_r ($dir);
?>
public function sortedScanDir($dir) {
// scan the current folder
$content = scandir($dir);
// create arrays
$folders = [];
$files = [];
// loop through
foreach ($content as $file) {
$fileName = $dir . '/' . $file;
if (is_dir($fileName)) {
$folders[] = $file;
} else {
$files[] = $file;
}
}
// combine
return array_merge($folders, $files);
}
There is a directory /home/example/public_html/users/files/. Within the directory there are subdirectories with random names like 2378232828923_1298295497.
How do I completely delete the subdirectories which have creation date > 1 month?
There is a good script that I use to delete files, but it don't work with dirs:
$seconds_old = 2629743; //1 month old
$directory = "/home/example/public_html/users/files/";
if( !$dirhandle = #opendir($directory) )
return;
while( false !== ($filename = readdir($dirhandle)) ) {
if( $filename != "." && $filename != ".." ) {
$filename = $directory. "/". $filename;
if( #filectime($filename) < (time()-$seconds_old) )
#unlink($filename); //rmdir maybe?
}
}
you need a recursive function for this.
function remove_dir($dir)
{
chdir($dir);
if( !$dirhandle = #opendir('.') )
return;
while( false !== ($filename = readdir($dirhandle)) ) {
if( $filename == "." || $filename = ".." )
continue;
if( #filectime($filename) < (time()-$seconds_old) ) {
if (is_dir($filename)
remove_dir($filename);
else
#unlink($filename);
}
}
chdir("..");
rmdir($dir);
}
<?php
$dirs = array();
$index = array();
$onemonthback = strtotime('-1 month');
$handle = opendir('relative/path/to/dir');
while($file = readdir($handle){
if(is_dir($file) && $file != '.' && $file != '..'){
$dirs[] = $file;
$index[] = filemtime( 'relative/path/to/dir/'.$file );
}
}
closedir($handle);
asort( $index );
foreach($index as $i => $t) {
if($t < $onemonthback) {
#unlink('relative/path/to/dir/'.$dirs[$i]);
}
}
?>
If PHP runs on a Linux server, you could use a shell command, to improve performance (a recursive PHP function can be inefficient in very large directories):
shell_exec('rm -rf '.$directory);