This question already has answers here:
What is the meaning of [] [closed]
(4 answers)
Closed 8 years ago.
I have been following a tutorial on readdir(), is_dir() etc involved in setting up a small image gallery based on folders and files on my FTP. I was wondering what the $directorys[] = $file; part does specifically?
while( $file= readdir( $dir_handle ) )
{
if( is_dir( $file ) ){
$directorys[] = $file;
}else{
$files[] = $file;
}
}
$directory is an array.
The code
$directory[] = $file
adds $file to the end of $directory array. This is the same as
array_push($directory, $file).
More info at array_push at phpdocs
$file will contain the name of the item that was scanned. In this case, the use of is_dir($file) allows you to check that $file in the current directory is a directory or not.
Then, using the standard array append operator [], the $file name or directory name is added to a $files/$directorys array...
It pushes an item to the array, instead of array_push, it would only push one item to the array.
Using array_push and $array[] = $item works the same, but it's not ideal to use array_push as it's suitable for pushing multiple items in the array.
Example:
Array (
)
After doing this $array[] = 'This works!'; or array_push($array, 'This works!') it will appear as this:
Array (
[0] => This works!
)
Also you can push arrays into an array, like so:
$array[] = array('item', 'item2');
Array (
[0] => Array (
[0] => item
[1] => item2
)
)
It adds the directory to the directory array :)
if( is_dir( $file ) ){
$directorys[] = $file; // current item is a directory so add it to the list of directories
}else{
$files[] = $file; // current item is a file so add it to the list of files
}
However if you use PHP 5 I really suggest using a DirectoryIterator.
BTW naming that $file is really bad, since it isn't always a file.
It creates a new array element at the end of the array and assigns a value to it.
Related
I have two arrays, $files with file names and $imagesFormats with formats of this images. I want to move every file from $files to directory given in $imageFormats. Indexes of files and it's formats are same in both arrays. What's the best way to do this - creating another associative array ($image => $format) or there is another solution?
If the two array have the same key you can do in the same foreach .. eg:
foreach( $files as $key => $value ) {
yourfunction($value); ///
yourfunction($imagesFormats [$key] ) ;
}
I have a script that scans a folder and put in an array the file names it contains.
Then I shuffle the array and display the file names.
Like this:
$count=0;
$ar=array();
$i=1;
$g=scandir('./images/');
foreach($g as $x)
{
if(is_dir($x))$ar[$x]=scandir($x);
else
{
$count++;
$ar[]=$x;
}
}
shuffle($ar);
while($i <= $count)
{
echo $ar[$i-1];
$i++;
}
?>
It works well but for some reason I get something like this:
fff.jpg
ccc.jpg
Array
nnn.jpg
ttt.jpg
sss.jpg
bbb.jpg
Array
eee.jpg
Of course, the order changes when I refresh the page because of the shuffle I did but among 200 filenames I always get these 2 "Array" somewhere in the list.
What could it be?
Thank you
Just to explain the part wherein it gives you the Array.
First off, scandir returns the following:
Returns an array of files and directories from the directory.
From that return values, it returned this (this is an example, for reference):
Array
(
[0] => . // current directory
[1] => .. // parent directory
[2] => imgo.jpg
[3] => logo.png
[4] => picture1.png
[5] => picture2.png
[6] => picture3.png
[7] => picture4.png
)
Those dots right there are actually folders. Right now in your code logic, when it hits/iterate this spot:
if(is_dir($x))$ar[$x]=scandir($x); // if its a directory
// invoke another set of scandir into this directory, then append it into the array
Thats why your resultant array has mixed strings, and that another extra/unneeded scandir array return values from ..
A dirty quick fix could be used in order to avoid those. Just skip the dots:
foreach($g as $x)
{
// skip the dots
if(in_array($x, array('..', '.'))) continue;
if(is_dir($x))$ar[$x]=scandir($x);
else
{
$count++;
$ar[]=$x;
}
}
Another alternative is to use DirectoryIterator:
$path = './images/';
$files = new DirectoryIterator($path);
$ar = array();
foreach($files as $file) {
if(!$file->isDot()) {
// if its not a directory
$ar[] = $file->getFilename();
}
}
echo '<pre>', print_r($ar, 1);
can anyone tell me why my code is only outputting 20 out of 40 files
$Files = array();
$dir = new DirectoryIterator('./images/gallery');
foreach($dir as $fileinfo){
if($fileinfo->isFile()){
$Files[$fileinfo->getMTime()] = $fileinfo->getFilename();
}
}
krsort($Files);
foreach($Files as $file){
echo "<a rel='fancy1' href='/images/gallery/$file'><span><img src='/images/revelsmashy.php?src=/images/gallery/$file&w=128&zc=0&q=100'></span></a>\n";
}
edit:
i am looking to sort images based on the data time they were uploaded with the latest one posted 1st
Your original method of indexing the array by the file's modification time looks to be resulting in files having the same mtime values overwriting previous array keys. In some circumstances, if your whole directory were rewritten at once, all files could have the same modification time so only the last one iterated will be in the resultant array.
If you need to ultimately sort by the time, you can instead build a multidimensional array which holds both filenames and file modification times and then sort it using usort().
$dir = new DirectoryIterator('./images/gallery');
foreach($dir as $fileinfo){
if($fileinfo->isFile()){
// Append each file as an array with filename and filetime keys
$Files[] = array(
'filename' => $fileinfo->getFilename(),
'filetime' => $fileinfo->getMtime()
);
}
}
// Then perform a custom sort:
// (note: this method requires PHP 5.3. For PHP <5.3 the you have to use a named function instead.
// see the usort() docs for examples )
usort($Files, function($a, $b) {
if ($a['filetime'] == $b['filetime']) return 0;
return $a['filetime'] < $b['filetime'] ? -1 : 1;
});
In your output loop, access the filename key:
foreach($Files as $file){
echo "<a rel='fancy1' href='/images/gallery/{$file['filename']}'><span><img src='/images/revelsmashy.php?src=/images/gallery/{$file['filename']}&w=128&zc=0&q=100'></span></a>\n";
//-----------------------------------------^^^^^^^^^^^^^^^^^^^^
}
I'm currently stuck trying to figure out how to sort my array files. I have a simple news posting system that stores the content in seperate .dat files and then stores them in an array. I numbered the files so that my array can sort them from lowest number to greatest; however, I have run into a small problem. To begin here is some more information on my system so that you can understand it better.
The function that gathers my files is:
function getNewsList() {
$fileList = array();
// Open the actual directory
if($handle = opendir(ABSPATH . ADMIN . "data")) {
// Read all file from the actual directory
while($file = readdir($handle)) {
if(!is_dir($file)) {
$fileList[] = $file;
}
}
}
// Return the array.
return $fileList;
}
On a seperate file is the programming that processes the news post. I didn't post that code for simplicity's sake but I will explain how the files are named. The files are numbered and the part of the post's title is used... for the numbering I get a count of the array and add "1" as an offset. I get the title of the post, encode it to make it file-name-friendly and limit the amount of text so by the end of it all I end up with:
// Make the variable that names the file that will contain
// the post.
$filename = "00{$newnumrows}_{$snipEncode}";
When running print_r on the above function I get:
Array (
[0] => 0010_Mira_mi_Soledad.dat
[1] => 0011_WOah.dat
[2] => 0012_Sinep.dat
[3] => 0013_Living_in_Warfa.dat
[4] => 0014_Hello.dat
[5] => 001_AS.dat
[6] => 002_ASASA.dat
[7] => 003_SSASAS.dat
...
[13] => 009_ASADADASADAFDAF.dat
)
And this is how my content is displayed. For some reason according to the array sorting 0010 comes before 001...? Is there a way I can get my array to sort 001 before 0010?
You can use natcasesort(array) function of php which will sort an array using a "natural order" algorithm and you will get the desired output
HTH.
:Malay
Take the filename and extract the prefix number as integer number:
// $filename has the format: "00{$newnumrows}_{$snipEncode}"
function generateSortKey($filename)
{
$separatorPos = stripos($filename, '_');
$prefix = trim(substr($filename, 0, $separatorPos));
return intval($prefix);
}
Than create an associative array from the list of files, the keys will be used as sortable value later:
function toSortableArray($files)
{
$result = array();
foreach ($files as $filename)
{
$key = generateSortKey($filename);
$value = $filename;
$result[$key] = $value;
}
return $result;
}
and at last use krsort():
$list = getNewsList();
$sortableList = toSortableArray($list);
krsort($sortableList); // after that $sortableList is
// sorted by key in descending order now
FIX: ksort() => krsort()
The issue is with underscore. Always numerical characters get sorted before underscore.
See whether you get the desired result using sort($your_array, SORT_NUMERIC).
For more info, refer PHP Manual for sort
You may also use natcasesort() (as Malay suggested) or natsort(). But both maintain index association.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
File creation time
In PHP, how to retrieve the files contained into a folder sorted by creation date (or any other sorting mechanism)?
According to the doc, the readdir() function:
The filenames are returned in the
order in which they are stored by the
filesystem.
save their information to an array, sort the array and then loop the array
if($h = opendir($dir)) {
$files = array();
while(($file = readdir($h) !== FALSE)
$files[] = stat($file);
// do the sort
usort($files, 'your_sorting_function');
// do something with the files
foreach($files as $file) {
echo htmlspecialchars($file);
}
}
That's my solution:
$fileList = array();
$files = glob('home/dir/*.txt');
foreach ($files as $file) {
$fileList[filemtime($file)] = $file;
}
ksort($fileList);
$fileList = array_reverse($fileList, TRUE);
print_r($fileList);
output is like this:
array(
(int) 1340625301 => '/home/dir/file15462.txt',
(int) 1340516112 => '/home/dir/file165567.txt',
(int) 1340401114 => '/home/dir/file16767.txt'
)
Then with "foreach" loop take the file you need.
You can store the files in an array, where the key is the filename and the value is the value to sort by (i.e. creation date) and use asort() on that array.
$files = array(
'file1.txt' => 1267012304,
'file3.txt' => 1267011892,
'file2.txt' => 1266971321,
);
asort($files);
var_dump(array_keys($files));
# Output:
array(3) {
[0]=>
string(9) "file2.txt"
[1]=>
string(9) "file3.txt"
[2]=>
string(9) "file1.txt"
}
Heh, not even the great DirectoryIterator can do that out of the box. Sigh.
There seems to be a pretty powerful script to do all that referenced here: preg_find. I've never worked with it but it looks good.
sorted in by filesize, in descending order?
$files = preg_find('/./', $dir,
PREG_FIND_RECURSIVE| PREG_FIND_RETURNASSOC |
PREG_FIND_SORTFILESIZE|PREG_FIND_SORTDESC);
$files=array_keys($files);
You could use scandir() to read the contents of the directory into an array, then use fileatime() or filectime() to see each file's access or creation time, respectively. Sorting the array from here shouldn't be too hard.
use shell_exec to execute command on os-level? on a linux/unix box this might work;
$output=shell_exec('ls -t1');