Locate file in from the file system root knowing sub-folder - php

I made this code below to find the path of file in my locat system, I would like to change this code to locate my-file and return its absolute path knowing that the only thing we remember about this file is that it is saved in a sub-folder /tmp/documents:
/tmp/documents can contain nested sub-folders and my-file can belong to any one of them.
If my-file cannot be found then your program should return NULL
Example:
locateFile() returns /tmp/documents/a/b/c/my-file if my-file is found into the folder /tmp/documents/a/b/c.
<?php
function locatefile(){
$flags = 0;
$pattern = 'my-file';
$files = glob($pattern, $flags);
foreach (glob(dirname($pattern) . '/*', GLOB_ONLYDIR | GLOB_NOSORT) as $dir)
{
$files = array_merge($files, locatefile($dir . '/' .basename($pattern), $flags));
}
return $files;
}
// code test do not change it
$folder = '/tmp/documents/' . rand() . '/' . rand();
mkdir($folder, 0700, true);
touch($folder . '/my-file');
echo "EXAMPLE:$folder/my-file\n";
echo "RESULT:" . locatefile();

Related

How can a create a folder and save a image on my server in php?

Below I have left my code. It currently works in my development environment (localhost), but when I push the changes to my live server it seems like my php doesn't create the folder/file.
public static function saveImage($image, $name, $path = '')
{
$img_data = explode(',', $image);
$mime = explode(';', $img_data[0]);
$data = $img_data[1];
$extension = explode('/', $mime[0])[1];
if(!file_exists('../public/media/img/' . $path)){
mkdir('../public/media/img/' . $path, 0755);
echo('Test1');
}
echo('test2');
file_put_contents('../public/media/img/' . $path . $name . '.' . $extension, base64_decode($data));
return 'media/img/' . $path . $name . '.' . $extension;
}
Locally it will hit echo('test1') the first time, then it will only hit echo('test2'). When its on the server it always hits the echo('test1')
By default mkdir is not create a path recursively. An example if on your server you dont have a ../public/media folder, mkdir returns false and dont create a path.
To solve this pass a third parameter to mkdir as true:
mkdir('../public/media/img/' . $path, 0755, true);
Do yourself a favour and use absolute pathes...
You can use the constant __DIR__ to evaluate the folder in which the script actually resides.
Relative pathes are calculated from the current working directory, which can be different than __DIR__

Extract a folder and then search for specific file in PHP

I´m building a php programm which uploads a zip file, extracts it and generates a link for a specific file in the extracted folder. Uploading and extracting the folder works fine. Now I´m a bit stuck what to do next. I have to adress the just extracted folder and find the (only) html file that is in it. Then a link to that file has to be generated.
Here is the code I´m using currently:
$zip = new ZipArchive();
if ($zip->open($_FILES['zip_to_upload']['name']) === TRUE)
{
$folderName = trim($zip->getNameIndex(0), '/');
$zip->extractTo(getcwd());
$zip->close();
}
else
{
echo 'Es gab einen Fehler beim Extrahieren der Datei';
}
$dir = getcwd();
$scandir = scandir($dir);
foreach ($scandir as $key => $value)
{
if (!in_array($value,array(".",".."))) //filter . and .. directory on linux-systems
{
if (is_dir($dir . DIRECTORY_SEPARATOR . $value) && $value == $folderName)
{
foreach (glob($value . "/*.html") as $filename) {
$htmlFiles[] = $filename; //this is for later use
echo "<a href='". SK_PICS_SRV . DIRECTORY_SEPARATOR . $filename . "'>" . SK_PICS_SRV . DIRECTORY_SEPARATOR . $filename . "</a>";
}
}
}
}
So this code seems to be working. I just noticed a rather strange problem. The $zip->getNameIndex[0] function behaves differently depending on the program that created the zip file. When I make a zip file with 7zip all seems to work without a problem. $folderName contains the right name of the main folder which I just extracted. For example "folder 01". But when I zip it with the normal windows zip programm the excat same folder (same structure and same containing files) the $zip->getNameIndex[0] contains the wrong value. For example something like "folder 01/images/" or "folder 01/example.html". So it seems to read the zip file differently/ in a wrong way. Do you guys know where that error comes from or how I can avoid it? This really seems strange to me.
Because you specify the extract-path by yourself you can try finding your file with php's function "glob"
have a look at the manual:
Glob
This function will return the name of the file matching the search pattern.
With your extract-path you now have your link to the file.
$dir = "../../suedkurier/werbung/"
$scandir = scandir($dir);
foreach ($scandir as $key => $value)
{
if (!in_array($value,array(".",".."))) //filter . and .. directory on linux-systems
{
if (is_dir($dir . DIRECTORY_SEPARATOR . $value))
{
foreach (glob($dir . DIRECTORY_SEPARATOR . $value . "/*.html") as $filename) {
$files[] = $value . DIRECTORY_SEPARATOR $filename;
}
}
}
}
The matched files will now be saved in the array $files (with the subfolder)
So you get your path like
foreach($files as $file){
echo $dir . DIRECTORY_SEPARATOR . $file;
}
$dir = "the/Directory/You/Extracted/To";
$files1 = scandir($dir);
foreach($files1 as $str)
{
if(strcmp(pathinfo($str, PATHINFO_EXTENSION),"html")===0||strcmp(pathinfo($str, PATHINFO_EXTENSION),"htm")===0)
{
echo $str;
}
}
Get an array of each file in the directory, check the extension of each one for htm/html, then echo the name if true.

Files listing include subdirectories and sorted tree

I have one main directory "Images" and many subdirectories - inside them are files (in main folder too). Example tree:
+Images
-first.jpg
-second.jpg
++FOLDER1
--image1.jpg
++FOLDER2
--image2.jpg
I found a script there:
function ListFiles($dir) {
if($dh = opendir($dir)) {
$files = Array();
$inner_files = Array();
while($file = readdir($dh)) {
if($file != "." && $file != ".." && $file[0] != '.') {
if(is_dir($dir . "/" . $file)) {
$inner_files = ListFiles($dir . "/" . $file);
if(is_array($inner_files)) $files = array_merge($files, $inner_files);
} else {
array_push($files, $dir . "/" . $file);
}
}
}
closedir($dh);
return $files;
}
}
$list = ListFiles('../upload/_thumbs/Images');
sort($list);
foreach ($list as $key=>$file){
echo '<option value="">'.$file.'</option>';
}
This script works fine but I can sort my results by folders (first main content, then rest)... I get i my select:
../upload/_thumbs/Images/first.jpg
../upload/_thumbs/Images/FOLDER1/image1.jpg
../upload/_thumbs/Images/FOLDER2/image2.jpg
../upload/_thumbs/Images/second.jpg
Expection:
../upload/_thumbs/Images/first.jpg
../upload/_thumbs/Images/second.jpg
../upload/_thumbs/Images/FOLDER1/image1.jpg
../upload/_thumbs/Images/FOLDER2/image2.jpg
I would be glad if you will help me! Thanks!
Well it probably has something to do with the sort function you call somewhere in the last lines
sort($list);
It's causing the array to sort alphabetical. You could try to leave it out, or you could try to use natsort.
natsort($list);
This is happening because you are sorting with the full path. Instead of sort, I would use uasort which is similar to sort, except you use a callback function to define which goes first.
alternatively, you could get by prepending the file name to the path and using the key on insert. In other words:
array_push($files, $dir . "/" . $file);
becomes:
$files[$file . $dir] = $dir . "/" . $file;
then you sort using ksort

Filepaths and Recursion in PHP

I'm trying to recursively iterate through a group of dirs that contain either files to upload or another dir to check for files to upload.
So far, I'm getting my script to go 2 levels deep into the filesystem, but I haven't figured out a way to keep my current full filepath in scope for my function:
function getPathsinFolder($basepath = null) {
$fullpath = 'www/doc_upload/test_batch_01/';
if(isset($basepath)):
$files = scandir($fullpath . $basepath . '/');
else:
$files = scandir($fullpath);
endif;
$one = array_shift($files); // to remove . & ..
$two = array_shift($files);
foreach($files as $file):
$type = filetype($fullpath . $file);
print $file . ' is a ' . $type . '<br/>';
if($type == 'dir'):
getPathsinFolder($file);
elseif(($type == 'file')):
//uploadDocsinFolder($file);
endif;
endforeach;
}
So, everytime I call getPathsinFolder I have the basepath I started with plus the current name of the directory I'm scandirring. But I'm missing the intermediate folders in between. How to keep the full current filepath in scope?
Very simple. If you want recursion, you need to pass the whole path as a parameter when you call your getPathsinFolder().
Scanning a large directory tree might be more efficient using a stack to save the intermediate paths (which would normally go on the heap), rather than use much more of the system stack (it has to save the path as well as a whole frame for the next level of the function call.
Thank you. Yes, I needed to build the full path inside the function. Here is the version that works:
function getPathsinFolder($path = null) {
if(isset($path)):
$files = scandir($path);
else: // Default path
$path = 'www/doc_upload/';
$files = scandir($path);
endif;
// Remove . & .. dirs
$remove_onedot = array_shift($files);
$remove_twodot = array_shift($files);
var_dump($files);
foreach($files as $file):
$type = filetype($path . '/' . $file);
print $file . ' is a ' . $type . '<br/>';
$fullpath = $path . $file . '/';
var_dump($fullpath);
if($type == 'dir'):
getPathsinFolder($fullpath);
elseif(($type == 'file')):
//uploadDocsinFolder($file);
endif;
endforeach;
}

Moving files into directory in foreach loop?

i've no idea how to do that and need your help!
i have an array of filenames called $bundle. (file_one.jpg, file_two.pdf, file_three.etc)
and i have the name of the folder stored in $folder. (my_directory)
i now would like to move all the files stored in $bundle to move to the directory $folder.
how can i do that?
//print count($bundle); //(file_one.jpg, file_two.pdf, file_three.jpg)
$folder = $folder = PATH . '/' . my_directory;
foreach ($bundle as $value) {
//rename(PATH.'/'.$value, $folder . '/' . $value);
}
just so it's not confusing: PATH just stores the local file-path im using for my project. in my case it's just the folder i'm working in-so it's "files".
i have no idea which method i have to use for this and how i could solve that!
thank you for your help!
The code given by you should work with minor changes:
$folder = PATH . '/' . 'my_directory'; // enclose my_directory in quotes.
foreach ($bundle as $value) {
$old = PATH.'/'.$value, $folder;
$new = $folder . '/' . $value;
if(rename($old,$new) !== false) {
// renamed $old to $new
}else{
// rename failed.
}
}
$folder = PATH . '/' . $folder;
foreach ($bundle as $value) {
$old = PATH.'/'.$value;
$new = $folder . '/' . $value;
if(rename($old,$new) !== false) {
// renamed $old to $new
}else{
// rename failed.
}
}
Untested but should work:
function bulkMove($src, $dest) {
foreach(new GlobIterator($src) as $fileObject) {
if($fileObject->isFile()) {
rename(
$fileObject->getPathname(),
rtrim($dest, '\\/') . DIRECTORY_SEPARATOR . $fileObject->getBasename()
);
}
}
}
bulkMove('/path/to/folder/*', '/path/to/new/folder');
Could add some checks to see if the destination folder is writable. If you dont need wildcard matching, change the GlobIterator to DirectoryIterator. That would also eliminate the need for PHP5.3

Categories