I'm creating a method that will inspect files in an upload folder and some of these files are archive (tar, tar.gz, zip, rar, etc). I would like to read these archive files and list all files in a nested tree format.
For example, I have an archive file called sandwich.tar.gz, I would like it to be listed as below:-
sandwich.tar.gz
lettuce
mayonaise
cheese
bread (directory)
wholemeal
My code thus far:-
<?php $archive = new PharData('/upload/directory/sandwich.tar.gz');
foreach($archive as $file) {
echo $file . "<br />";
}
But it failed to list files inside the bread directory. How do I fix this?
You can do this using a RecursiveIteratorIterator, because PharData extends the Phar class and the Phar class extends the RecursiveDirectoryIterator class:
$archive = new PharData('/upload/directory/sandwich.tar.gz');
foreach (new RecursiveIteratorIterator($archive) as $file) {
echo $file . "<br />";
}
Although this question is rather dated, considering the stupidity and the uselessness of the previous answer, I cannot but reply.
It seems whatever PHP does is always non-standard and awkward at best...
You got it right to inspect the first level. However, the objects returned from the iteration are not of the same type, thus calling foreach on them will lead to failure.
Iterating on a PharData object gives you PharFileInfo ones. From there you can check for the file type (checking if it is a directory with the inherited isDir() method).
From there, you will need to create another PharData object on the path to the resource obtained from the (also inherited) getPathname() (sic, not getPathName() say the docs!) method. You will then be able to iterate over it...
Full example:
<?php
$archive = new PharData('/upload/directory/sandwich.tar.gz');
foreach($archive as $file) {
echo $file;
if($file->isDir()) {
echo ':';
$dir = new PharData($file->getPathname());
foreach($dir as $child) {
echo "<br />$child";
}
}
echo "<br />";
}
?>
Of course, that kills easy recursion if you have multiple levels in your archive. You will have to cook your own recursive crawler...
Some advice that I was given once, and think about often, comes to mind: code will do EXACTLY what you ask it to do: nothing more, nothing less.
Ask the machine: 'if this is a directory, please display the contents?'
Your function thinks that it is looking for a $file, and thus outputs the name of that file.
Consider http://php.net/manual/en/function.readdir.php and http://www.php.net/manual/en/function.is-dir.php
Related
For each document (.pdf, .txt, .docx ecc) I have also a corresponding json file with the same filename.
Example:
file1.json,
file1.pdf,
file2.json,
file2.txt,
filex.json,
filex.pdf,
But I got also some json files which are not accompanied with the corresponding document.
I want to delete all json files which have no corresponding document. Im really stucked because I cant find a proper solution to my problem.
I know how to scandir() get the filename, extensions from pathinfo() ecc. but the issue is that for each json file I find in directory I have to perform another foreach on that directory excluding all json files and see If the same filename exists or not so than I can decide to delete it. (This is how I think to solve it).
The problem here is with performance since there are millions of files and for each json I have to run a foreach on millions of files.
Can anyone guide me to a better solution?
Thank you!
Edit: Since no one will help without first posting a piece of code (and this approach in stackoverflow is definitively wrong) here is how I'm trying.:
<?php
$dir = "2000/";
$files = scandir($dir);
foreach ($files as $file) {
$fullName = pathinfo($file);
if ($fullName['extension'] === 'json') {
if (!in_array($fullName['filename'].'.pdf', $files)){
unlink($dir.$file);
}
}
}
Now as you can see I can only search only for one type of document (.pdf in this case). I want to search for every extension excluding .json and also I don't want that for each json file to run a foreach/in_array() but achieving all this in just one foreach.
Maybe you should consider it in another way? I mean, iterate through all files, and try to find corresponding files to json, if not found remove it.
It would look like follows:
$dir = "2000/";
foreach (glob($dir . "*.json") as $file) {
$file = new \SplFileInfo($dir . $file);
if (count(glob($dir . $file->getBasename('.' . $file->getExtension()) . ".*")) === 1) {
unlink($dir . $file->getFilename());
}
}
Manual
PHP: SplFileInfo
PHP: glob
I'm making a simple file listing function in PHP, just to recursively list all the files in a directory.
The function I have right now looks something like this:
<?php
function listFiles($dir){
echo "<ul class=\"filebrowser\">";
$dirCont = scandir($dir); // scan the whole directory
sortFoldersFirst($dirCont,$dir); // sort alphabetically, folders first
foreach ($dirCont as $value) {
if (!in_array($value,array(".","..",".deleted"))){ // don't list the parent folder, current folder, or the (hidden) .deleted folder
if (is_dir($dir . DIRECTORY_SEPARATOR . $value)){ // if it's a folder
echo "<h3 class=\"filebrowser\">" . $value . "</h3>"; // show the folder name
listFiles($dir . DIRECTORY_SEPARATOR . $value); // do the same again for the child folder
} else {
echo "<li>".$value."</li>"; // a link to the file
}
}
}
echo "</ul>";
}
?>
This gives me something like this:
This technique works just fine, however, I'd like to store a little more information about the files, like the author, comments, maybe a link to a thumbnail etc.
I'd like to get rid of the 'real' directory structure, and store everything in a database. (Just all files in 1 big folder, and links to the files in the database, not the actual files)
How can I store this information in the database, and how can I get it back out, without changing the result in the browser.
In other words: how can I get the tree structure in and out of the database, and how do I recursively loop through it.
I found this answer.
It shows how to make a database tree structure by saving the parent folder's id for every file/folder. This makes it easy to get the full path of a file, but it seems a bit less convenient to list all contents of a folder.
Is there a better solution to this problem?
Thanks in advance,
Pieter
I have seen a few example on the web but they seem pretty messy. I am looking for a nice and clean way to say, get me only the files/folders that have .zip on them. What I have so far is:
foreach(scandir(__DIR__) as $files) {
var_dump($files);
}
What I wonder is is if I need pre match or if the ZipArchive class has any functions that state "return only files with .zip
This should work for you, you can use glob():
<?php
foreach (glob("*.zip") as $filename) {
echo $filename . "<br />";
}
?>
possible Output:
test - Kopie.zip
test.zip
test2.zip
For more information about glob() see the manual: http://php.net/manual/en/function.glob.php
I have audio files in var/
This is the file name
2-3109999999-3246758493-1271129518-1271129505.6.wav
Format
2=campaign id
3109999999=caller id
3246758493=number called
1271129518=timestamp call ended
1271129505=timestamp call started
6=call id
If I were to pass just the number called which was 3246758493, how can I find all the files without defining all the other variables(such as timestamp, etc) and just the files that have that number in the filename?
You would need to loop though the folder: http://php.net/manual/en/function.readdir.php
Then for each of the files in the folder, try and match it to the file that was requested using regex I guess?
http://www.txt2re.com/index-php.php3?s=2-3109999999-3246758493-1271129518-1271129505.6.wav&8
You could also use a DirectoryIterator to scan the folder and a RegexIterator to filter the files based on a pattern.
$id = '3246758493';
$files = new RegexIterator(new DirectoryIterator('var/'),
"#^\d-\d{10}-$id-\d{10}-\d{10}\.\d\.wav$#D");
foreach ($files as $fileinfo) {
echo $fileinfo . PHP_EOL;
}
I'm trying to design a program in PHP that would allow me to find files with specific file extensions (example .jpg, .shp etc) in a known directory which consists of multiple folders.
Sample code, documentation or information about what methods I will be required to use will be much appreciated.
glob is pretty easy:
<?php
foreach (glob("*.txt") as $filename) {
echo "$filename size " . filesize($filename) . "\n";
}
?>
There are a few suggestions for recursive descent at the readdir page.
Take a look at PHP's SPL DirectoryIterator.
I believe PHP's glob() function is exactly what you are looking for:
http://php.net/manual/en/function.glob.php
Use readdir to get a list of files, and fnmatch to work out if it matches your required filename pattern. Do all this inside a function, and call your function when you find directories. Ask another question if you get stuck implementing this (or comment if you really have no idea where to start).
glob will get you all the files in a given directory, but not the sub directories. If you need that too, you will need to: 10. get recursive, 20. goto 10.
Here's the pseudo pseudocode:
function getFiles($pattern, $dir) {
$files = glob($dir . $pattern);
$folders = glob($dir, GLOB_ONLYDIR);
foreach ($folders as $folder) {
$files = $files + getFiles($folder);
}
return $files;
}
The above will obviously need to be tweaked to get it working, but hopefully you get the idea (remember not to follow directory links to ".." or "." or you'll be in infinite loop town).