i'm using this function to list all files in a folder and its sub-folders
function printAll($dirName){
$dirs=array($dirName);
$files=array();
while($dir=array_pop($dirs)){
$handle=opendir($dir);
while($file=readdir($handle)){
if($file!='.' && $file!='..'){
$dest=$dir.'/'.$file;
if(is_file($dest)){
$files[]=$file;
echo $file;
}else{
$dirs[]=$dest;
}
}
}//end of 1st while
}//end of 2nd while
return $files;
}//end of function
printAll(getcwd());
But is there a way i can sort alphabetically the list of the filenames ?
You can use php's sort method, to perform sorting.
First, don't echo the file names on line 11.
//echo $file;
Next use this snippet:
$files_list = printAll(getcwd());
sort($files_list);
print_r( $files_list );
You're better off using scandir for this kind of thing. Due to the slightly odd thing you're requesting, it's inbuilt sorting won't finish the job (due to the grabbing the files in the directory below), but PHP's in built array sorting (in this case, natsort) should do the job fine.
function getDir($folder){
$folderFiles = scandir($folder);
$files = Array();
foreach($folderFiles as $filename){
if($filename==="." || $filename==="..") continue;
if(is_dir($folder."/".$filename)){
$files = array_merge($files, getDir($folder."/".$filename));
}else{
$files[] = $filename;
}
}
return $files;
}
$files = getDir("./");
natsort($files);
$files = array_values($files);
echo "<pre>";
print_r($files);
echo "</pre>";
Related
I Want To Get List Of Files In My Directories & Sub-Directories In An Array In PHP Language .
I Have 2 Type Of Code :
1- First Code:
This Bellow Code List All Files In An Array , But There Are Folders And Sub-directories In Array :
$files = dir_scan('pathAddress');
function dir_scan($folder) {
$files = glob($folder);
foreach ($files as $f) {
if (is_dir($f)) {
$files = array_merge($files, dir_scan($f .'/*')); // scan subfolder
}
}
return $files;
}
echo "<pre>";
print_r($files);
echo "</pre>";
Result Of Top Code : Click For View Image
2- Second Code:
This Bellow Code List All MP3 Files But In String Not Array! & I Can't Convert It To Array.
$scan_it = new RecursiveDirectoryIterator("pathAddress");
foreach(new RecursiveIteratorIterator($scan_it) as $file) {
if (strtolower(substr($file, -4)) == ".mp3") {
echo "<pre>";
echo($file);
echo "</pre>";
}
}
Result Of Top Code : Click For View Image
Finally, I Want An Array Of MP3 Files In All Directories & Sub-Directories Specified Location .
Thanks For Your Help
This code might help you, It will check all the folders and in return, will get file names ..
<?php
function listFolderFiles($dir)
{
$file_names = array();
foreach (new DirectoryIterator($dir) as $fileInfo) {
if (!$fileInfo->isDot()) {
if ($fileInfo->isDir()) {
// checking directory empty or not, if not then append list
$isDirEmpty = !(new \FilesystemIterator($fileInfo->getPathname()))->valid();
if($isDirEmpty != 1)
{
$file_names[] = listFolderFiles($fileInfo->getPathname());
}
}
else
{
$file_names[] = $fileInfo->getPathname() ;
}
}
}
// Splicing Array
for ($i=0; $i<count($file_names); $i++) {
if (is_array($file_names[$i])) {
array_splice($file_names, $i, 1, $file_names[$i]);
}
}
return $file_names;
}
$res = listFolderFiles('main_folder_name');
echo '<pre>';
print_r($res);
?>
I'm having trouble getting my code to work the way I want.
I'm using scandir to get all files from the directory. This gives me a list with pdf files linked to a product, but the problems comes with the posibllity of pdf files multiple languages. Like so:
1096_EN.pdf
867_PT.pdf
914_EN.pdf
914_NL.pdf
Before _ is ID and after language. And I want the user to only see one file per product.
my code looks likes this:
$files = scandir($dir);
foreach ($files as $file)
{
$exp_file = explode("_", $file);
// check file for given ID
if($exp_file[0] == $_GET['iD']){
// check file for userlanguage
if($exp_file[1] == $lang){
echo $file;
}
// check file in english
elseif($exp_file[1] == "EN"){
echo $file;
}
// return available file in other language
else{
echo $file;
}
}
}
In case of 914 and NL the code returns two files. In case of 914 and PT i only get 1 file, 914_EN.pdf and in case of 867 and NL there will be zero files.
What is the best way to filter my files and return the best matched file? I personally think the error is in the for loop, but I cant find a proper way out..
thanks
If you want to have just the single items, you should keep a backlog of which you have already processed, as the foreach loop will go from for example 914_EN.pdf to 914_NL.pdf, while the checks have already been completed for 914_EN.pdf, so when you get to 914_NL.pdf, it just reruns the checks and thinks it is okay.
if working with multiple same values, you can first cleanse the array to get what you wanted. You can take a look at this, if this what you want. Cheers!
$files = array("1096_EN.pdf", "867_PT.pdf", "914_EN.pdf", "914_NL.pdf");
$new_exp_file = array();
foreach ($files as $file) {
$exp_file = explode("_", $file);
$new_exp_file[] = $exp_file[0];
}
$new_exp_file_arr_ = array_values(array_unique($new_exp_file));
for($i = 0, $file_ctr = count($new_exp_file_arr_); $i < $file_ctr; $i++) {
if($new_exp_file_arr_[$i] == "914") {
echo $new_exp_file_arr_[$i] . "<br>";
echo "<ul>";
foreach ($files as $file) {
$exp_file = explode("_", $file);
if($new_exp_file_arr_[$i] == $exp_file[0]) {
echo "<li>" . $exp_file[1] . "</li>";
}
}
echo "</ul>";
}
}
this seems to work for me? Using a regex probably not as efficient as the above methods though.
$_GET['iD'] = 1096;
$ptn = "^((\d+)\_([a-zA-Z]+)\.([a-zA-Z]+))^";
$aFiles = array('1096_EN.pdf','867_PT.pdf','914_EN.pdf','914_NL.pdf');
$lang = "EN";
foreach ($aFiles as $sFileName)
{
preg_match($ptn, $sFileName, $aFileParts);
var_dump($aFileParts);
// check file for given ID
if($aFileParts[2] == $_GET['iD']){
// check file for userlanguage
if(strtolower($aFileParts[3]) == strtolower($lang)){
echo $sFileName;
break;
}
// return available file in other language
else{
echo $sFileName;
}
}
}
I've solved my problem by the following:
if(glob($_GET['iD']."_".$_GET['t']."*.pdf"))
{
$file = glob($_GET['iD']."_".$_GET['t']."*.pdf");
echo $file[0];
}
else
{
if(glob($_GET['iD']."_EN*.pdf"))
{
$file = glob($_GET['iD']."_EN*.pdf");
echo $file[0];
}
else
{
$file = glob($_GET['iD']."*.pdf");
echo $file[0];
}
}
No more looping, just checking for different files with wildcards. Works like a charm. I.m.o. much cleaner with larger lists of files..
I'm writing a script that matches a list of items with an image, which is stored in a folder and possibly sub-folders of this main folder. I want to take all files within the main/sub-folders and put them in an array.
I have a function which finds all files but doesn't lump them in a single array (so that I can easily match the item with image - it is much harder if its multi-dimensional).
function listFolderFiles($dir){
$ffs = scandir($dir);
echo '<ol>';
$images = [];
foreach($ffs as $ff){
if($ff != '.' && $ff != '..'){
echo '<li>'.$ff;
if(is_dir($dir.'/'.$ff)) listFolderFiles($dir.'/'.$ff);
echo '</li>';
$images[] = $ff;
}
}
echo "<pre>";
print_r($images);
echo '</ol>';
}
listFolderFiles("K:\\");
Any ideas on how I can do flatten the resultant array?
Just merge them:
function listFolderFiles($dir) {
$files = glob("$dir/*");
foreach($files as $f) {
if(is_dir($f)) {
$files = array_merge($files, (array)listFolderFiles($f));
}
}
return $files;
}
foreach(listFolderFiles('/path') as $file) {
echo "<li>$file</li>";
}
Edited. Lots of ways but do it when you call the function maybe.
To return an array instead of printing the HTML, you will obviously remove the echo commands.
First, define the array at the beginning of the function, such as $return = array();
Now, instead of echoing $ff, you use $return[] = $ff;
Then, instead of just making a recursive call, you want to merge the new array into your current one with array_merge($return, listFolderFiles($dir.'/'.$ff));
Finally, return at the end: return $return;
I could use some help with this. I have to get list of files from one directory, and return them as array, but key needs to be the same as value, so output would be looking like this:
array(
'file1.png' => 'file1.png',
'file2.png' => 'file2.png',
'file3.png' => 'file3.png'
)
I found this code:
function images($directory) {
// create an array to hold directory list
$results = array();
// create a handler for the directory
$handler = opendir($directory);
// open directory and walk through the filenames
while ($file = readdir($handler)) {
// if file isn't this directory or its parent, add it to the results
if ($file != "." && $file != "..")
{
$results[] = $file;
}
}
// tidy up: close the handler
closedir($handler);
// done!
return $results;
}
It's working fine, but it returns regular array.
Can someone help me with this?
Also small note at the end, I need to list only image files (png,gif,jpeg).
Change your following line
$results[] = $file;
To
$results[$file] = $file;
To limit file extension do as below
$ext = pathinfo($file, PATHINFO_EXTENSION);
$allowed_files = array('png','gif');
if(in_array($ext,$allowed_files)){
$results[$file] = $file;
}
Something like this should to the work
$image_array = [];
foreach ($images as $image_key => $image_name) {
if ($image_key == $image_name) {
$image_array[] = $image_name;
}
return $image_array;
}
Why not using glob and array_combine ?
function images($directory) {
$files = glob("{$directory}/*.png");
return array_combine($files, $files);
}
glob() get files on your directory according to a standard pattern ( such as *.png )
array_combine() creates an associative array using an array of keys and an array of values
now do this on my script
$scan=scandir("your image directory");
$c=count($scan);
echo "<h3>found $c image.</h3>";
for($i=0; $i<=$c; $i++):
if(substr($scan[$i],-3)!=='png') continue;
echo "<img onClick=\"javascript:select('$scan[$i]');\" src='yourdirectory/$scan[$i]' />";
endfor;
this code only list png images from your directory.
PHP manual for scandir: By default, the sorted order is alphabetical in ascending order.
I'm building a file browser (in Windows), so I want the addresses to be returned sorted by folder/file, then alphabetically in those subsets.
Example: Right now, I scan and output
Aardvark.txt
BarDir
BazDir
Dante.pdf
FooDir
and I want
BarDir
BazDir
FooDir
Aardvark.txt
Dante.pdf
Other than a usort and is_dir() solution (which I can figure out myself), is there a quick and efficient way to do this?
The ninja who wrote this comment is on the right track - is that the best way?
Does this give you what you want?
function readDir($path) {
// Make sure we have a trailing slash and asterix
$path = rtrim($path, '/') . '/*';
$dirs = glob($path, GLOB_ONLYDIR);
$files = glob($path);
return array_unique(array_merge($dirs, $files));
}
$path = '/path/to/dir/';
readDir($path);
Note that you can't glob('*.*') for files because it picks up folders named like.this.
Please try this. A simple function to sort the PHP scandir results by files and folders (directories):
function sort_dir_files($dir)
{
$sortedData = array();
foreach(scandir($dir) as $file)
{
if(is_file($dir.'/'.$file))
array_push($sortedData, $file);
else
array_unshift($sortedData, $file);
}
return $sortedData;
}
I'm late to the party but I like to offer my solution with readdir() rather than with glob(). What I was missing from the solution is a recursive version of your solution. But with readdir it's faster than with glob.
So with glob it would look like this:
function myglobdir($path, $level = 0) {
$dirs = glob($path.'/*', GLOB_ONLYDIR);
$files = glob($path.'/*');
$all2 = array_unique(array_merge($dirs, $files));
$filter = array($path.'/Thumbs.db');
$all = array_diff($all2,$filter);
foreach ($all as $target){
echo "$target<br />";
if(is_dir("$target")){
myglobdir($target, ($level+1));
}
}
}
And this one is with readdir but has basically the same output:
function myreaddir($target, $level = 0){
$ignore = array("cgi-bin", ".", "..", "Thumbs.db");
$dirs = array();
$files = array();
if(is_dir($target)){
if($dir = opendir($target)){
while (($file = readdir($dir)) !== false){
if(!in_array($file, $ignore)){
if(is_dir("$target/$file")){
array_push($dirs, "$target/$file");
}
else{
array_push($files, "$target/$file");
}
}
}
//Sort
sort($dirs);
sort($files);
$all = array_unique(array_merge($dirs, $files));
foreach ($all as $value){
echo "$value<br />";
if(is_dir($value)){
myreaddir($value, ($level+1));
}
}
}
closedir($dir);
}
}
I hope someone might find this useful.