PHP array as variable for diffent array? - php

How can I load multiple vars each containing a single path into an array variable?
$dir1 = "/path/1/";
$dir2 = "/path/2/";
$dir3 = array($dir1, $dir2);
$directories = array($dir3);
$count = 0;
foreach ($directories as $dir) {
$files = glob("{$dir}*.gz") ?: array();
$count += count($files);
}
When I print $dir3 I get both paths as an array but I cannot get the $dir3 var for $directories to work. I have tried looking for answers but I am unable to find similar use cases. The documentation on php.net is also unclear to me. I'm still new to PHP and programming in general.
I want to figure out how I can have multiple paths in a single var but still have foreach execute on each path in the var.

$dir3 already is an array containing your directories.
By doing $directories = array($dir3);, you're therefore creating an array of arrays.
So you could simply replace your code with:
$dir1 = "/path/1/";
$dir2 = "/path/2/";
$directories = array($dir1, $dir2); // or $directories = [$dir1, $dir2];
$count = 0;
foreach ($directories as $dir) {
$files = glob("{$dir}*.gz");
$count += count($files);
}
However, as #MarkusZeller has pointed out, you can also pass a comma separated list of directories directly to glob, using the GLOB_BRACE flag:
$dir1 = "/path/1/";
$dir2 = "/path/2/";
$commaSeparatedDirectories = implode(',', [$dir1, $dir2]);
$count = count(glob("{{$commaSeparatedDirectories}}*.gz", GLOB_BRACE));

Related

List of files and Folder

actully i get the folder and files from perticular path but its doesnt returns the value what i want.
im expecting the return value like:-
[{"filename":"19_0_0_0_0_1.jpg","RFI":19},
{"filename":"19_0_0_0_0_2.jpg","RFI":19},
{"filename":"19_20005_1_0_0_1.jpg","RFI":19},
{"filename":"19_20005_1_0_0_2.jpg","RFI":19},
{"filename":"19_20005_1_429_0_1.jpg","RFI":19},
{"filename":"19_20005_1_429_0_2.jpg","RFI":19},
{"filename":"19_20005_1_429_1_1.jpg","RFI":19},
{"filename":"19_20005_1_429_1_2.jpg","RFI":19},
{"filename":"19_20027_1_0_0_1.jpg","RFI":19}]
and its give me like this output :
[{"filename":[{"filename":"19_0_0_0_0_1.jpg","RFI":19},
{"filename":"19_0_0_0_0_2.jpg","RFI":19},
{"filename":"19_20005_1_0_0_1.jpg","RFI":19},
{"filename":"19_20005_1_0_0_2.jpg","RFI":19},
{"filename":"19_20005_1_429_0_1.jpg","RFI":19},
{"filename":"19_20005_1_429_0_2.jpg","RFI":19},
{"filename":"19_20005_1_429_1_1.jpg","RFI":19},
{"filename":"19_20005_1_429_1_2.jpg","RFI":19},
{"filename":"19_20027_1_0_0_1.jpg","RFI":19}],"RFI":19}]
this is my code:
$ldir = "D:\php\EIL_App\RFIImages";
$data = listFolderFiles($ldir,19);
print json_encode($data);
function listFolderFiles($dir,$pRFI)
{
$result = array();
foreach (new DirectoryIterator($dir) as $fileInfo){
if (!$fileInfo->isDot()){
$dataimg = $fileInfo->getFilename();
if($fileInfo->getFilename() == $pRFI){
if ($fileInfo->isDir()){
$dataimg = listFolderFiles($fileInfo->getPathname(),$pRFI);
}
array_push($result,array('filename'=>$dataimg,'RFI'=>$pRFI));
}
}
}
return $result;
}
Please give the suggestion what can i do???
Thanks in advance.
There's no need to complicate things
$prefix = 19;
$dir = "D:\php\EIL_App\RFIImages";
$data = glob("$prefix*.*",19); // it will give you array with all files matching pattern
// then you can do a loop
$arr = [];
foreach ($data as $filename) {
$arr[] = ['filename' => $filename, 'prefix' => $prefix];
}
echo json_encode($arr);
http://php.net/manual/en/function.glob.php
If you want to use iterator then use glob http://php.net/manual/en/globiterator.construct.php
Regarding your code
if ($fileInfo->isDir()) this makes no sense because it will never go to this if. It's because before you check if (!$fileInfo->isDot()){ and dot means either . or .. which applies to directories. If you want to do it recursively then you can use
Edit:
I've noticed you do some recursion if so then probably it'd be better to use ResursiveIterator
function listFolderFiles($dir, $prefix) {
$rii = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($dir));
$files = new RegexIterator($rii, "^$prefix.*", RegexIterator::GET_MATCH); // note prefix cannot have characters that are special to regex or they should be escaped
$arr = array();
foreach($files as $file) {
$arr[] = $file;
}
return $arr;
}
http://php.net/manual/en/class.recursivedirectoryiterator.php
http://php.net/manual/en/directoryiterator.isdot.php

PHP only first level of subdirectories into an array

I'm trying to get only the first level of subdirectories into an array.
Does someone know a slimmer and faster way to do this?
$dirs = new RecursiveDirectoryIterator('myroot', RecursiveDirectoryIterator::SKIP_DOTS);
$files = new RecursiveIteratorIterator($dirs, RecursiveIteratorIterator::SELF_FIRST);
$dir_array = array();
foreach( $files AS $file)
{
if($files->isDot()) continue;
if($files->getDepth() > 0) continue;
if( $files->isDir() )
{
$dir_array[] = $file->getFilename();
}
}
Simple as this:
$array = glob('myroot/*', GLOB_ONLYDIR);
To get only the base directory name and not the full path:
$array = array_map('basename', glob('myroot/*', GLOB_ONLYDIR));
See http://php.net/glob

php DirectoryIterator sort files by date

I'm using php's DirectoryIterator class to list files in a directory. I can't however figure out an easy way to sort files by date. How is this done with DirectoryIterator
<?php
$dir = new DirectoryIterator('.');
foreach ($dir as $fileinfo) {
echo $fileinfo->getFilename() . '<br>';
}
?>
What if i name my files like whatever_2342345345.ext where the numbers represents time in milliseconds so each file has a unique number. How can we sort by looking at the numbers after underscore
If you need to sort, build an array and sort that.
$files = array();
$dir = new DirectoryIterator('.');
foreach ($dir as $fileinfo) {
$files[$fileinfo->getMTime()][] = $fileinfo->getFilename();
}
ksort($files);
This will build an array with the modified time as the key and an array of filenames as the value. It then sorts via ksort(), which will give you the filenames in order of time modified.
If you then want to re-flatten the structure to a standard array, you can use...
$files = call_user_func_array('array_merge', $files);
If you still want to access all the data available at DirectoryIterator (e.g. isDot() getSize() etc) a possible way is to store the Iterator key on the array you are going to sort, and seek the DirectoryIterator later.
$sorted_keys = array();
$dir_iterator = new DirectoryIterator('.');
foreach ( $dir_iterator as $fileinfo )
{
$sorted_keys[$fileinfo->getMTime()] = $fileinfo->key();
}
ksort($sorted_keys);
/* Iterate `DirectoryIterator` as a sorted array */
foreach ( $sorted_keys as $key )
{
$dir_iterator->seek($key);
$fileinfo = $dir_iterator->current();
/* Use $fileinfo here as a normal DirectoryIterator */
echo $fileinfo->getFilename() . ' ' . $fileinfo->getSize() . '<br>';
}
In case multiple files have the same modified time (updated):
$files = array();
$mtimes = array();
$dir = new DirectoryIterator('.');
foreach($dir as $file){
if(!$file->isFile())
continue;
$mtime = $file->getMTime();
if(!$mtimes[$mtime]){
$files[$mtime.'.0'] = $file->getFilename();
$mtimes[$mtime] = 1;
}else{
$files[$mtime.'.'.$mtimes[$mtime]++] = $file->getFilename();
}
}
ksort($files);

PHP how to get all files(only html files) in all subdirectories and index each html page

For a homework assignment, I have to get all the .htm and .html files in the current and all sub directories, and I have to index them by counting all the words that appear in the files individually.
Here is how I would count the file once I find an html file in a directory:
$file = '.html';
$index = indexer($file);
echo '<pre>'.print_r($index,true).'</pre>';
function indexer($file) {
$index = array();
$find = array('/\r/','/\n/','/\t/','!',',','.','"',';', ':');
$replace = array(' ',' ',' ',' ',' ',' ',' ',' ',' ');
$string = file_get_contents($file);
$string = strip_tags($string);
$string = strtolower($string);
$string = str_replace($find, $replace, $string);
$string = trim($string);
$string = explode(' ', $string);
natcasesort($string);
$i = 0;
foreach($string as $word) {
$word = trim($word);
$ignore = preg_match('/[^a-zA-Z]/', $word);
if($ignore == 1) {
$word = '';
}
if( (!empty($word)) && ($word != '') ) {
if(!isset($index[$i]['word'])) {
$index[$i]['word'] = $word;
$index[$i]['count'] = 1;
} elseif( $index[$i]['word'] == $word ) {
$index[$i]['count'] += 1;
} else {
$i++;
$index[$i]['word'] = $word;
$index[$i]['count'] = 1;
}
}
}
unset($work);
return($index);
}
I just need to figure out first how to find all the htm or html files in the directories and then start using the above code on each htm/html file. Any help will be appreciated, thanks!
Well, because this is a homework assignment, I won't give you the code. But I can point you in the right direction. Usually for this type of thing, people with use a recursive function. Where a function calls itself.
This function should do the following:
Count all the lines of all the htm, and html files in the current directory.
Add these numbers up, and then add them to a global variable outside the function (just use global, you could return the number of lines each call, and add them up, but that is a pain in the butt)
call this function again for every folder in the current directory (just loop through them)
once you are back at the very start, reset the global variable, and return its value
The RecursiveDirectoryIterator is the best class in PHP to do this. It's flexible and fast.
Other alternative methods (not recursive) are described in "Directory to array with PHP". In my answer to that question, I timed the different methods given by other answers, but all of the solutions in PHP code are slower than using the PHP's SPL classes.
Here's an alternative using RecursiveIteratorIterator, RecursiveDirectoryIterator and pathinfo().
<?php
$dir = '/';
$iterator = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($dir), RecursiveIteratorIterator::CHILD_FIRST);
foreach ( $iterator as $path )
if ( $path->isFile() && preg_match('/^html?$/i', pathinfo($path->getFilename(), PATHINFO_EXTENSION)) )
echo $path->getPathname() . PHP_EOL;
If you need to get the current working directory, you can use getcwd() (i.e. $dir = getcwd();).
To get the length of the content, you can do a few things. You could retrieve the contents of the file using file_get_contents and use strlen to calculate the length or str_word_count to count the words. Another option could be to use $path->getSize().
If you use an array to store the names and the sizes, you can then use a custom function and uasort to sort the array by sizes.
A more complete example:
<?php
function sort_by_size($a, $b)
{
if ( $a['size'] == $b['size'] )
return 0;
return ( $a['size'] < $b['size'] ? -1 : 1 );
}
$dir = '/';
$files = array();
$iterator = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($dir), RecursiveIteratorIterator::CHILD_FIRST);
foreach ( $iterator as $path )
if ( $path->isFile() && preg_match('/^html?$/i', pathinfo($path->getFilename(), PATHINFO_EXTENSION)) )
$files[] = array(
'name' => $path->getPathname(),
'size' => $path->getSize()
);
uasort($files, sort_by_size);
The $files array can then be looped through using a foreach loop. It will contain both the pathname and the size.
Try Using glob function.
$files = glob('*.htm*');
foreach($files as $file) {
//code here
}
Edited:
function readDir($path) {
$files = glob($path . '*.*');
foreach ($files as $file) {
if (is_dir($file)) {
$html_files = array_merge((array) readDir($file . '/'), (array) $html_files);
}
if (in_array(strtolower(end(explode('.', $file))), array('html', 'htm'))) {
$html_files[] = $file;
}
}
return $html_files;
}
Just edited the answer, Try this. (Note: I haven't Not tested the code on any site.)
Thanks
Do you have any restrictions on the functions/classes you can use? If not, then check out RecursiveDirectoryIterator it will let you go through dirs recursively iterating over all the items in the directory. You could then match the extension on each item and if it matches basically do your counting.
An alternative approach to this would be to use glob while iterating over the directories which allows you to do a *.html search like you would use with with the *nix utility find.
As far as counting you might want to take look at str_word_count.

Get folders with PHP glob - unlimited levels deep

I have this working function that finds folders and creates an array.
function dua_get_files($path)
{
foreach (glob($path . "/*", GLOB_ONLYDIR) as $filename)
{
$dir_paths[] = $filename;
}
return $dir_paths;
}
This function can only find the directories on the current location. I want to find the directory paths in the child folders and their children and so on.
The array should still be a flat list of directory paths.
An example of how the output array should look like
$dir_path[0] = 'path/folder1';
$dir_path[1] = 'path/folder1/child_folder1';
$dir_path[2] = 'path/folder1/child_folder2';
$dir_path[3] = 'path/folder2';
$dir_path[4] = 'path/folder2/child_folder1';
$dir_path[5] = 'path/folder2/child_folder2';
$dir_path[6] = 'path/folder2/child_folder3';
If you want to recursively work on directories, you should take a look at the RecursiveDirectoryIterator.
$path = realpath('/etc');
$objects = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($path), RecursiveIteratorIterator::SELF_FIRST);
foreach($objects as $name => $object){
echo "$name\n";
}
Very strange - everybody advice recursion, but better just cycle:
$dir ='/dir';
while($dirs = glob($dir . '/*', GLOB_ONLYDIR)) {
$dir .= '/*';
if(!$result) {
$result = $dirs;
} else {
$result = array_merge($result, $dirs);
}
}
Try this instead:
function dua_get_files($path)
{
$data = array();
$files = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($path), RecursiveIteratorIterator::SELF_FIRST);
foreach ($files as $file)
{
if (is_dir($file) === true)
{
$data[] = strval($file);
}
}
return $data;
}
Use this function :
function dua_get_files($path)
{
$dir_paths = array();
foreach (glob($path . "/*", GLOB_ONLYDIR) as $filename)
{
$dir_paths[] = $filename;
$a = glob("$filename/*", GLOB_ONLYDIR);
if( is_array( $a ) )
{
$b = dua_get_files( "$filename/*" );
foreach( $b as $c )
{
$dir_paths[] = $c;
}
}
}
return $dir_paths;
}
You can use php GLOB function, but you must create a recursive function to scan directories at infinite level depth. Then store results in a global variable.
function dua_get_files($path) {
global $dir_paths; //global variable where to store the result
foreach ($path as $dir) { //loop the input
$dir_paths[] = $dir; //can use also "basename($dir)" or "realpath($dir)"
$subdir = glob($dir . DIRECTORY_SEPARATOR . '*', GLOB_ONLYDIR); //use DIRECTORY_SEPARATOR to be OS independent
if (!empty($subdir)) { //if subdir is not empty make function recursive
dua_get_files($subdir); //execute the function again with current subdir
}
}
}
//usage:
$path = array('galleries'); //suport absolute or relative path. support one or multiple path
dua_get_files($path);
print('<pre>'.print_r($dir_paths,true).'</pre>'); //debug
For PHP, if you are on a linux/unix, you can also use backticks (shell execution) with the unix find command. Directory searching on the filesystem can take a long time and hit a loop -- the system find command is already built for speed and to handle filesystem loops. In other words, the system exec call is likely to cost far less cpu-time than using PHP itself to search the filesystem tree.
$dirs = `find $path -type d`;
Remember to sanitize the $path input, so other users don't pass in security compromising path names (like from the url or something).
To put it into an array
$dirs = preg_split("/\s*\n+\s*/",`find $path -type d`,-1,PREG_SPLIT_NO_EMPTY);

Categories