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);
Related
I want to create a unique array to show which folders got deleted. All files are stored in a .txt and can only be read.
function createUniqueArr(array $arr){
$uniqueArray = array();
foreach($arr as $i => $string){
foreach($uniqueArray as $j => $string){
if(!(str_contains($uniqueArray[$j], $arr[$i]))){
$uniqueArray[$j] = $arr[$i];
}
}
}
return $uniqueArray;
}
This is the code i have so far but it does not seem to work.
NOTE: The full Folder name is in the array before all subfiles.
The array that is given looks like this, every new line is a new index:
test/test/folder1
test/test/folder1/example.txt
test/test/folder1/example2.txt
test/test/folder1/example3.txt
test/test/folder1/example4.txt
test/test/folder1/example5.txt
test/thisFolderShoudBeShownFully/example6.txt
The disered array should be something like this:
> test/test/folder1
> test/thisFolderShoudBeShownFully/example6.txt
Hope someone can help me
I'd iterate over the list once to get an array of the directories, then again to exclude lines that have a directory in that list. This doesn't require the input to be sorted such that the directory lines are first.
$dirs = array_filter($list, fn($line) => !preg_match('/\.txt$/', $line));
$new = array_filter($list, fn($line) => !in_array(dirname($line), $dirs));
print_r($new);
Array
(
[0] => test/test/folder1
[6] => test/thisFolderShoudBeShownFully/example6.txt
)
I have a simple PHP script with this snippet of code:
$files = scandir($dir);
print_r($files);
And noticed in my array i have:
[0] => .
[1] => ..
[2] => assets.php
[3] => loader.php
Is this a bug on my server or is it expected behavior, what are they? And if it's the latter is there any way to exclude them from the scan? As I wish to only get script files that I made from the directory and nothing else. Is there any way to exclude them from the scan?
No it isn't a bug.... . is the current directory, .. the parent directory
See the PHP Docs
The user-contributed notes show one way of excluding them:
$directory = '/path/to/my/directory';
$scanned_directory = array_diff(scandir($directory), array('..', '.'));
If you use other options besides scandir, such as SPL's DirectoryIterator, there's options to exclude them (such as combining it with a RegexIterator), or to test for them as you're iterating:
$iterator = new DirectoryIterator(dirname(__FILE__));
foreach ($iterator as $fileinfo) {
if (!$fileinfo->isDot()) {
echo $fileinfo->getFilename() . "\n";
}
}
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!
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.