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');
Related
This question already has answers here:
Using a string path to set nested array data [duplicate]
(8 answers)
Closed 3 years ago.
I am trying to find a way to create an array of directories. But as we all know directories can have many subDirs and those subDirs can have more subDir and so on and on. The directories length are unknown as it can change.
Say I have a directory as www/webs/apps/pics and another www/webs/test.
The idea would be to have an array such as: (yes the below is json, i just converted it in my php demonstration because i find it easier to read)
{
"www": {
"webs": {
"apps": {
"pics": "Im Here"
}
},
"test": "im Here too"
}
}
There is no relation from the above output to the below code. The below code is here just to give an idea what I need.
$exploedDir = explode("/", $unsortedDir);
foreach ($exploedDir as $dir){
$this->allDirectiroesFound[$dir] = $dir;
}
How can I make $this->allDirectiroesFound has as many dimensions as it is needed without knowing the length of the directory, I cant hard code $this->allDirectiroesFound[][][][][][] it as next time around the array length might be [][][].
You can just reverse each of the path arrays and then go on creating the Keys from the last directory.
$paths = [
'www/webs/apps/pics',
'www/webs/test',
];
$finalArray = [];
foreach($paths as $path){
$revArr = array_reverse(explode("/", $path)); // This is the trick. Start to build from inside out.
$pathArray = [];
foreach($revArr as $key){
$tempBucket = $pathArray;
$pathArray = []; // Create fresh empty array to hold the
$pathArray[$key] = $tempBucket;
}
$finalArray = array_merge_recursive($pathArray, $finalArray); // Recursively Merge the array into the main array
}
echo "<pre>";
print_r(json_encode($finalArray, JSON_PRETTY_PRINT));
echo "</pre>";
DEMO
I guess you would need to use arrays of arrays to solve this.
e.g.
var directories = ["base"];
var subdir1 = ["subdir1"];
var subsubdir1 = ["subsubdir1"];
var subsubdir1 = ["subsubdir2"];
subdir.push(subsubdir1);
subdir.push(subsubdir2);
directories.push(subdir1);
so this forms a base->subdir1->[subsubdir1, subsubdir2] structure. The complication comes in ensuring that every 'push' you perform is an array to allow adjacent siblings to exist for that particular sub-directory. That and keeping track of the directory structure
I am working with copying files, I can copy one file to multi folders, but I have problem when copying multi files to multi folders.
My code :
$sourcefiles = array('./folder1/test.txt', './folder1/test2.txt');
$destinations = array('./folder2/test.txt', './folder2/test2.txt');
//do copy
foreach($sourcefiles as $source) {
foreach($destinations as $des){
copy($source, $des);
}
}
But this code not work !
Could you give me a solution :(
Thanks for any help !
What you currently do is looping the sourcefiles, which in the first itteration is "test.txt" and then you loop the destination array and performing the copy function 2 times:
1st iteration with folder1/test.txt
copy("folder1/test.txt", "folder2/test.txt");
copy("folder1/test.txt", "folder2/test2.txt";
2nd iteration with folder1/test2.txt:
copy("folder1/test2.txt", "folder2/test.txt");
copy("folder1/test2.txt", "folder2/test2.txt";
In the end you've overwritten both files with the last file in your $source array. So both files in "folder2" contain the data of test2.txt
What you are looking for would be:
foreach($sourcefiles as $key => $sourcefile) {
copy($sourcefile, $destinations[$key]);
}
$sourcefile equals $sourcefiles[$key] in the above example.
This is based on the fact that PHP automatically assigns keys to your values. $sourcefiles = array('file1.txt', 'file2.txt'); can be used as:
$sourcefiles = array(
0 => 'file1.txt',
1 => 'file2.txt'
);
Another option is to use the length of one of the arrays in a for loop, which does the same thing but in a different way:
for ($i = 0; $i < count($sourcefiles); $i++) {
copy($sourcefiles[$i], $destinations[$i]);
}
I think what you're trying to do is this;
for ($i = 0; $i < count($sourcefiles); $i++) {
copy($sourcefiles[$i], $destinations[$i]);
}
You current code will overwrite previous copies.
Assuming you have equal amount of files:
// php 5.4, lower version users should replace [] with array()
$sources = ['s1', 's2'];
$destinations = ['d1', 'd2'];
$copy = [];
foreach($sources as $index => $file) $copy[$file] = $destinations[$index];
foreach($copy as $source => $destination) copy($source, $destination);
Since you need the same index for both arrays, use a for loop.
for ($i = 0; $i < count($sourcefiles); $i++) {
//In here, $sourcefiles[$i] is the source, and $destinations[$i] is the destination.
}
Of course not. Your nested loop is copying the files in such a way that they're bound to overwrite previous file copies. I think you need to use a simpler solution. Copying in a nested loop doesn't make any sense.
If you have the source and destination files, then I suggest a single loop:
$copyArray = array(
array('source' => './folder1/test.txt', 'destination' => './folder2/test.txt'),
array('source' => './folder1/test.txt', 'destination' => './folder2/test.txt'));
foreach ($copyArray as $copyInstructions)
{
copy($copyInstructions['source'], $copyInstructions['destination']);
}
But make sure your destination file-names are different!
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";
//-----------------------------------------^^^^^^^^^^^^^^^^^^^^
}
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.
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.