I'm trying to create a folder tree from an array, taken from a string.
$folders = str_split(564);
564 can actually be any number. The goal is to create a folder structure like /5/6/4
I've managed to create all folders in a single location, using code inspired from another thread -
for ($i=0;$i<count($folders);$i++) {
for ($j=0;$j<count($folders[$i]);$j++) {
$path .= $folders[$i][$j] . "/";
mkdir("$path");
}
unset($path);
}
but this way I get all folders in the same containing path.
Furthermore, how can I create these folders in a specific location on disk? Not that familiar with advanced php, sorry :(
Thank you.
This is pretty simple.
Do a for each loop through the folder array and create a string which appends on each loop the next sub-folder:
<?php
$folders = str_split(564);
$pathToCreateFolder = '';
foreach($folders as $folder) {
$pathToCreateFolder .= DIRECTORY_SEPARATOR . $folder;
mkdir($folder);
}
You may also add the base path, where the folders should be created to initial $pathToCreateFolder.
Here you'll find a demo: http://codepad.org/aUerytTd
Or you do it as Michael mentioned in comments, with just one line:
mkdir(implode(DIRECTORY_SEPARATOR, $folders), 0777, TRUE);
The TRUE flag allows mkdir to create folders recursivley. And the implode put the directory parts together like 5/6/4. The DIRECTORY_SEPARATOR is a PHP constant for the slash (/) on unix machines or backslash (\) on windows.
Why not just do:
<?php
$directories = str_split(564);
$path = implode(DIRECTORY_SEPARATOR, $directories);
mkdir($path, 0777, true);
Don't know what you're really trying to do, but here are some hints.
There are recursive mkdir:
if(!file_exists($dir)) // check if directory is not created
{
#mkdir($dir, 0755, true); // create it recursively
}
Path you want can be made in two function calls and prefixed by some start path:
$path = 'some/path/to/cache';
$cache_node_id = 4515;
$path = $path.'/'.join('/', str_split($cache_node_id));
Resulting path can be used to create folder with the code above
So here we come to a pair of functions/methods
function getPath($node_id, $path = 'default_path')
{
return $path.'/'.join('/', str_split($node_id))
}
function createPath($node_id, $path = 'default_path');
{
$path = getPath($node_id, $path);
if(!file_exists($path)) // check if directory is not created
{
#mkdir($path, 0755, true); // create it recursively
}
}
With these you can easily create such folders everywhere you desire and get them by your number.
As mentioned earlier, the solution I got from a friend was
$folders = str_split(564);
mkdir(implode('/',$folders),0777,true);
Also, to add a location defined in a variable, I used
$folders = str_split($idimg);
mkdir($path_defined_earlier. implode('/',$folders),0777,true);
So thanks for all the answers, seems like this was the correct way to handle this.
Now the issue is that I need to the created path, so how can I store it in a variable? Sorry if this breaches any rules, if I need to create a new thread I'll do it...
Related
Say I want my uploaded files to be stored in a structure of subdirectories as shown below:
/uploads/0/0/kitten.jpg;
/uploads/0/1/kitten1.jpg;
/uploads/1/10/pic.jpg;
So that each subfolder can contain 999 files at max i.e. when /uploads/0/ reaches its limit, the folder /uploads/1/ is created automaticaly and next file goes there. Each folder also can contain 999 subfolders.
The question is - How do I do that? My main concern is how to determine where to put the newly uploaded file. Could you describe the algorithm? I cannot think of anything better than performing these steps each time:
Looking for the latest created folder in /uploads/ and if it's empty - creating one, like so:
$contents = $scandir('/uploads');
$dirs = array();
foreach ($contents as $path) {
if (is_dir($path)) {
$dirs[] = $path;
}
}
if (empty($dirs)) {
//create new dir and save file there subsequently
$saveTo = $parentDir . DIRECTORY_SEPARATOR . "1" . DIRECTORY_SEPARATOR . "1";
mkdir($saveTo, 0777, true);
} else {
$last = array_pop($dirs);
}
We do basically the same for this subfolder and so on(and I guess I may want to use recursion here somehow). Am I moving in right direction here or maybe I am overcomplicating things? Is there a better way to do this? Anything, please. I am only beginner in php and coding.
One approach is to keep a running total of all uploads, (atomically) increasing it for each upload.
Then the directory can be created like so:
$dir = sprintf('/uploads/%d/%d', floor($total / 1000), $total % 1000);
if (!file_exists($dir)) {
mkdir($dir, 0755, true);
}
I'm having problems checking if a dinamically named folder exists using php. I know i can use
file_exists()
to check if a folder or file exists, but the problem is that the name of the folders I'm checking may vary.
I have folders where the first part of the name is fixed, and the part after "_" can vary. As an example:
folder_0,
where every folder will start with "folder_" but after the "_" it can be anything.
Anyway i can check if a folder with this property exists?
Thanks in advance.
SR
You make a loop to go through all the files/folders in the parent folder:
$folder = '/path-to-your-folder-having-subfolders';
$handle = opendir($folder) or die('Could not open folder.');
while (false !== ($file = readdir($handle))) {
if (preg_match("|^folder_(.*)$|", $file, $match)) {
$curr_foldername = $match[0];
// If you come here you know that such a folder exists and the full name is in the above variable
}
}
function find_wildcard_dirs($prefix)
{
return array_filter(glob($prefix), 'is_dir');
}
e.g.
print_r(find_wildcard_dirs("/tmp/santos_*'));
I am trying to list files in subdirectories and write these lists into separate text files.
I managed to get the directory and subdirectory listings and even to write all the files into a text file.
I just don't seem to manage to burst out of loops I am creating. I either end up with a single text file or the second+ files include all preceeding subdirectories content as well.
What I need to achieve is:
dir A/AA/a1.txt,a2.txt >> AA.log
dir A/BB/b1.txt,b2.txt >> BB.log
etc.
Hope this makes sense.
I've found the recursiveDirectoryIterator method as described in PHP SPL RecursiveDirectoryIterator RecursiveIteratorIterator retrieving the full tree being great help. I then use a for and a foreach loop to iterate through the directories, to write the text files, but I cannot break them into multiple files.
Most likely you are not filtering out the directories . and .. .
$maindir=opendir('A');
if (!$maindir) die('Cant open directory A');
while (true) {
$dir=readdir($maindir);
if (!$dir) break;
if ($dir=='.') continue;
if ($dir=='..') continue;
if (!is_dir("A/$dir")) continue;
$subdir=opendir("A/$dir");
if (!$subdir) continue;
$fd=fopen("$dir.log",'wb');
if (!$fd) continue;
while (true) {
$file=readdir($subdir);
if (!$file) break;
if (!is_file($file)) continue;
fwrite($fd,file_get_contents("A/$dir/$file");
}
fclose($fd);
}
I thought I'd demonstrate a different way, as this seems like a nice place to use glob.
// Where to start recursing, no trailing slash
$start_folder = './test';
// Where to output files
$output_folder = $start_folder;
chdir($start_folder);
function glob_each_dir ($start_folder, $callback) {
$search_pattern = $start_folder . DIRECTORY_SEPARATOR . '*';
// Get just the folders in an array
$folders = glob($search_pattern, GLOB_ONLYDIR);
// Get just the files: there isn't an ONLYFILES option yet so just diff the
// entire folder contents against the previous array of folders
$files = array_diff(glob($search_pattern), $folders);
// Apply the callback function to the array of files
$callback($start_folder, $files);
if (!empty($folders)) {
// Call this function for every folder found
foreach ($folders as $folder) {
glob_each_dir($folder, $callback);
}
}
}
glob_each_dir('.', function ($folder_name, Array $filelist) {
// Generate a filename from the folder, changing / or \ into _
$output_filename = $_GLOBALS['output_folder']
. trim(strtr(str_replace(__DIR__, '', realpath($folder_name)), DIRECTORY_SEPARATOR, '_'), '_')
. '.txt';
file_put_contents($output_filename, implode(PHP_EOL, $filelist));
});
I have the following code snippet. I'm trying to list all the files in a directory and make them available for users to download. This script works fine with directories that don't have sub-directories, but if I wanted to get the files in a sub-directory, it doesn't work. It only lists the directory name. I'm not sure why the is_dir is failing on me... I'm a bit baffled on that. I'm sure that there is a better way to list all the files recursively, so I'm open to any suggestions!
function getLinks ($folderName, $folderID) {
$fileArray = array();
foreach (new DirectoryIterator(<some base directory> . $folderName) as $file) {
//if its not "." or ".." continue
if (!$file->isDot()) {
if (is_dir($file)) {
$tempArray = getLinks($file . "/", $folderID);
array_merge($fileArray, $tempArray);
} else {
$fileName = $file->getFilename();
$url = getDownloadLink($folderID, $fileName);
$fileArray[] = $url;
}
}
}
Instead of using DirectoryIterator, you can use RecursiveDirectoryIterator, which provides functionality for iterating over a file structure recursively. Example from documentation:
$path = realpath('/etc');
$objects = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($path), RecursiveIteratorIterator::SELF_FIRST);
foreach($objects as $name => $object){
echo "$name\n";
}
This prints a list of all files and
directories under $path (including
$path ifself). If you want to omit
directories, remove the
RecursiveIteratorIterator::SELF_FIRST
part.
You should use RecursiveDirectoryIterator, but you might also want to consider using the Finder component from Symfony2. It allows for easy on the fly filtering (by size, date, ..), including dirs or files, excluding dirs or dot-files, etc. Look at the docblocks inside the Finder.php file for instructions.
I'd love some help....i'm not sure where to start in creating a script that searches for a folder in a directory and if it doesnt exist then it will simply move up one level (not keep going up till it finds one)
I am using this code to get a list of images. But if this folder didn't exist i would want it to move up to its parent.
$iterator = new DirectoryIterator("/home/domain.co.uk/public_html/assets/images/bg-images/{last_segment}"); foreach ($iterator as $fileinfo) {
if ($fileinfo->isFile() && !preg_match('/-c\.jpg$/', $fileinfo->getFilename())) {
$bgimagearray[] = "'" . $fileinfo->getFilename() . "'";
} }
Put your directory name in a variable.
$directory = "/home/domain.co.uk/public_html/assets/images/bg-images/{last_segment}";
// if directory does not exist, set it to directory above.
if(!is_dir($directory)){
$directory = dirname($directory)
}
$iterator = new DirectoryIterator($directory);
It works: file_exists($pathToDir)
To test if a directory exists, use is_dir()
http://php.net/function.is-dir
To move up to the parent directory would be by chdir('..');
http://php.net/function.chdir