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!
Related
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);
According to http://assemblysys.com/php-point-in-polygon-algorithm/ I can take a group of points that form a polygon and determine whether or not a point resides inside or outside the polygon. I have also created an KML file when is being utilized by JavaScript to determine which points are inside, however my end goal would to have each marker contain an extra data set inside of a MySQL table that will store this data for later use resulting in a quicker map load time.
Looking through the KML file, each Polygon has a set of coordinates that are separated by ",0.0" which means little because according to the above document I only need the set of lats and longs. In addition, the latitudes and longitudes are in different places. Below is an example of the cordinates:
-86.1459875,39.8622513,0.0 -86.1459875,39.8555639,0.0 -86.1398077,39.8556628,0.0 -86.1398077,39.862218399999996,0.0 -86.1459875,39.8622513,0.0
Instead I want the set to look like the following:
39.8622513 -86.1459875, 39.8555639 -86.1459875, 39.8556628 -86.1398077, 39.862218399999996 -86.1398077, 39.8622513 -86.1459875
Below is a sample of my code, however I am not sure if there is an easier way of manipulating the array using PHP without the use of multiple for loops or foreach loops.
$kml = 'document.xml';
//get the total number polygons
$numPoly = count( $kml->Document[0]->Folder);
$newArray = array();
$a = 1;
$explode;
$explode['coordinates'];
for( $i=0; $i <= $numPoly; $i++)
{
$numPlace = count( $kml->Document[0]->Folder[$i]->Placemark); //count the number of placemarks there are
for($z = 0; $z <= $numPlace; $z++)
{
$regionName = $kml->Document[0]->Folder[$i]->Placemark[$z]->name."</br>"; //grab each placemarks name
//get the cordinates inside of each placemark
$regionCords = $kml->Document[0]->Folder[$i]->Placemark[$z]->Polygon->outerBoundaryIs->LinearRing->coordinates;
//print_r($regionCords); print "<br/><br/>";
foreach($regionCords as $num2 => $region)
{
print $a;
$explodeCords = array_splice( explode('|', str_replace(',0.0',' |', $regionCords) ), 0, -1 ) ;
foreach ($explodeCords as $exploded)
{
$exploded = explode(',', $exploded);
$exploded1 = $exploded[0];
$exploded2 = $exploded[1];
$explodedString = $exploded2.$exploded1.",";
//echo $explodedString; echo "<br/><br/>";
}
}
$numCordinates = count($explodeCords['coordinates'] ); //returns the number of [lat,long] cords in each cordinate set
if ( !empty( $regionCords ) )
{
$a++;
}
}
}
Please let me know if I am on the right path or if there is another way you can easily switch these two numbers using mostly array functions with PHP.
A solution: after each foreach loop, it is best practice to remove the new array out of the loop, because if you are to add another foreach loop, unwanted effects may result such as appending a value to a new array in multiples.
After the values are removed from the foreach loop, you can always use a array_map to switch the coordinates. For a more completed example of this please see the following Github repo: https://github.com/jdmagic21/GMapParse
I would like to pass in an array that contains a list of directories to scan. I want to iterate over each directory and push its content into another array that I will print out, but for some reason my code is not working. The directories exist and the path is correct. I think it has something to do with how I'm using foreach.
These are the errors I'm getting:
Notice: Undefined index: C:\Users\john\Desktop\files\images\ in
C:\xampp\htdocs\test.php on line 6
Warning: scandir(): Directory name cannot be empty in
C:\xampp\htdocs\test.php on line 6
This is the code:
function test($dir = []) {
foreach($dir as $bar) {
$list = [];
array_push($list, scandir($dir[$bar]));
}
print_r($list);
}
test(["C:\Users\john\Desktop\files\images\\", "C:\Users\john\Desktop\files\images\autumn\\"]);
If anyone can think of a simpler way to do this, please don't hesitate to tell me.
You're on the right track. There are a few changes you need to make though.
function test($dir = []) {
$list = [];
foreach($dir as $bar) {
$list[] = scandir($bar);
}
print_r($list);
}
As noted by #BrianPoole you need to move the $list out of the foreach loop. By having it in the loop, the array is reset with each iteration, resulting in the final array having one element.
In addition, the foreach loop as explained above by #TimCooper does not operate the same as in JavaScript. If you really want to access the keys, you can use the following syntax:
foreach($dir as $key => $bar)
You would then use either $dir[$key] or $bar to access the directory value.
Finally, array_push is an additional function call that in your case is not needed. By simply adding [] PHP will push the new value onto the end of the array.
function test($dir) {
// DEFINE LIST OUT SIDE OF LOOP
$list = array();
// Run checks
if(count($dir) > 0) {
// Loop Through Directory
foreach($dir as $directory) {
// Push into list
array_push($list, array("scanned"=>$directory, "contents" => scandir($directory)));
}
}else {
// If no directories are passed return array with error
$list = array(
"error" => 1,
"message" => "No directories where passed into test()",
);
}
print_r($list);
}
This is how I would do it. It provides a couple checks and sets up the data so you can se it a bit more clear.
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";
//-----------------------------------------^^^^^^^^^^^^^^^^^^^^
}
We can get the files in a directory in PHP by
$files = new DirectoryIterator()
after that is there an easy way to sort the items in a particular order for displaying them? thanks.
It doesn't look like there is a way to sort the data within the iterator.
You could place the display data into an intermediary array, with a key of the value you wish to sort by, and call ksort() on the array. This will take two passes over the data however.
$path = ".";
$files = new DirectoryIterator($path);
$files_array = array();
while($files->valid()) {
// sort key, ie. modified timestamp
$key = $files->getMTime();
$data = $files->getFilename();
$files_array[$key] = $data;
$files->next();
}
ksort($files_array);
foreach($files_array as $key => $file){
print $key . " => " . $file . "\n";
}
edit:
if you place all of the information that you want to output for the files in the array values, you can simply implode() the array afterwards, instead of looping through the data once again.
$files = new DirectoryIterator($path);
$i = 0;
$paths = array();
while($files->valid()) {
$paths[$i++] = $files->getFileName();
$files->next();
}
sort($paths)
May be what you are looking for, you can always of course apply the sort function to sort the paths depending on your preference after that.