I'm using PharData to create a tar package. It works fine but it includes a folder i don't want. How can I exclude a folder in the archive?
<?php
$dir = "/foobar/dir";
$iterator = new RecursiveIteratorIterator(
new RecursiveDirectoryIterator($dir)
);
$phar = new PharData('/mytar.tar');
$phar->buildFromIterator($iterator, $dir);
$phar->compress(Phar::GZ);
unlink(realpath('/mytar.tar'));
The folder I want to ignore in the archive is vendor (/foobar/dir/vendor).
You can use CallbackFilterIterator() to filter the unwanted files and folders (not tested yet):
<?php
$dir = "/foobar/dir";
$iterator = new RecursiveIteratorIterator(
new RecursiveDirectoryIterator($dir)
);
$filterIterator = new CallbackFilterIterator($iterator , function ($file) {
return (strpos($file, "vendor/") === false);
});
$phar = new PharData('/mytar.tar');
$phar->buildFromIterator($filterIterator, $dir);
$phar->compress(Phar::GZ);
unlink(realpath('/mytar.tar'));
Related
I have a top folder named home and nested folders and files inside
I need to insert some data from files and folders into a table
The following (simplified) code works fine if I manually declare parent folder for each level separatelly, i.e. - home/lorem/, home/impsum/, home/ipsum/dolor/ etc
Is there a way to do this automatically for all nested files and folders ?
Actually, I need the path for each of them on each level
$folders = glob("home/*", GLOB_ONLYDIR);
foreach($folders as $el){
//$path = ??;
//do_something_with folder;
}
$files = glob("home/*.txt");
foreach($files as $el){
//$path = ??;
//do_something_with file;
}
PHP has the recursiveIterator suite of classes - of which the recursiveDirectoryIterator is the correct tool for the task at hand.
# Where to start the recursive scan
$dir=__DIR__;
# utility
function isDot( $dir ){
return basename( $dir )=='.' or basename( $dir )=='..';
}
# create new instances of both recursive Iterators
$dirItr=new RecursiveDirectoryIterator( $dir, RecursiveDirectoryIterator::KEY_AS_PATHNAME );
$recItr=new RecursiveIteratorIterator( $dirItr, RecursiveIteratorIterator::CHILD_FIRST );
foreach( $recItr as $obj => $info ) {
# directories
if( $info->isDir() && !isDot( $info->getPathname() ) ){
printf('> Folder=%s<br />',realpath( $info->getPathname() ) );
}
# files
if( $info->isFile() ){
printf('File=%s<br />',$info->getFileName() );
}
}
I would suggest you to use The Finder Component
use Symfony\Component\Finder\Finder;
$finder = new Finder();
// find all files in the home directory
$finder->files()->in('home/*');
// To output their path
foreach ($finder as $file) {
$path = $file->getRelativePathname();
}
I have a function which is working fine to create zip file from folder files. But recently I've had need to add sub-folders into my main folder and now I see my function does not add those sub-folders and files in them into generated zip file.
here is what I have currently:
$zip = new ZipArchive;
if ($zip->open(public_path('Downloads/new_zip.zip'), ZipArchive::CREATE) === TRUE)
{
$files = File::files(public_path('new_zip'), true);
foreach ($files as $key => $value) {
$relativeNameInZipFile = basename($value);
$zip->addFile($value, $relativeNameInZipFile);
}
$zip->close();
}
By using code above, let say I have following structure:
new_zip
sample.txt
It works fine to create zip file for my folder.
But
If my folder structure is like:
new_zip
sample.txt
folder_a
file_a.txt
folder_b
folder_c
file_c.txt
Then it ignores everything from folder_a and beyond.
Any suggestions?
You can use this method
The 1st argument is the path to the directory whose data you want to compress
The 2nd argument is the path to the resulting zip file
for your case:
createZipArchive(public_path('new_zip'), public_path('Downloads/new_zip.zip'))
function createZipArchive(string $sourceDirPath, string $resultZipFilePath): bool
{
$zip = new ZipArchive();
if (true !== $zip->open($resultZipFilePath, ZipArchive::CREATE | ZipArchive::OVERWRITE)) {
return false;
}
/** #var SplFileInfo[] $files */
$files = new RecursiveIteratorIterator(
new RecursiveDirectoryIterator($sourceDirPath),
RecursiveIteratorIterator::LEAVES_ONLY
);
foreach ($files as $file) {
$filePath = $file->getRealPath();
if ($file->isDir() || !$filePath) {
continue;
}
$relativePath = substr($filePath, strlen($sourceDirPath) + 1);
$zip->addFile($filePath, $relativePath);
}
return $zip->close();
}
This method will fully reproduce the folder structure of the source directory.
and a little bit of clarification:
To add the directory "test_dir" and the file "test.txt" to the archive - you just need to do:
$zip->addFile($filePath, "test_dir/test.txt");
The RecursiveDirectoryIterator and RecursiveIteratorIterator are used to recursively traverse the directories of the source folder. They are part of the standard php library. You can read about them in the official php documentation
I have a folder with subfolders containing all kind of files..
When I trigger action to delete them, some of them got deleted but some of them don't. What I am trying to say is that they are all pretty much same structure.. I don't know what is causing that? Is it something with timing or? I am deleting the folder with files once the zip files are created.
This is the method which is deleting folder with subfolders and files..
private function removeFiles($name)
{
// Locate folder to remove
$rootDirElements = [
$this->kernel->getProjectDir(),
$name
];
$rootDir = implode(DIRECTORY_SEPARATOR, $rootDirElements);
$rdi = new RecursiveDirectoryIterator($rootDir, RecursiveDirectoryIterator::SKIP_DOTS);
$files = new RecursiveIteratorIterator(
$rdi,
RecursiveIteratorIterator::CHILD_FIRST
);
foreach ($files as $file) {
if ($file->isDir()) {
rmdir($file->getRealPath());
} else {
unlink($file->getRealPath());
}
}
rmdir($rootDir);
}
And I am calling it in another method where zip logic is happening:
private function zipFolder($source, $destination, $name, $includeDir = false)
{
$zip = new ZipArchive();
if ($zip->open($destination, ZipArchive::CREATE | ZipArchive::OVERWRITE) === true) {
//zipping logic
}
}
}
}
$zip->close();
// After zip file is created delete folder
$this->removeFiles($name);
I don't know what is causing that?
I'm using RecursiveDirectoryIterator to scan for all files and folders within a given root dir. This works fine, but I'd like to keep track of all of the unique directories in that list, so I'm not sure that RecursiveDirectoryIterator is the way to go.
I have a directory structure of
-a
->b
->c
-one
->two
->three
Here is my code:
<?php
function test($dir){
$in_dir = 'none';
$currdir = 'none';
$thisdir = new RecursiveDirectoryIterator($dir, RecursiveDirectoryIterator::SKIP_DOTS);
$files = new RecursiveIteratorIterator($thisdir, RecursiveIteratorIterator::SELF_FIRST);
foreach($files as $object){
//if this is a directory... find out which one it is.
if($object->isDir()){
//figure out if we have changed directories...
$currdir = realpath($object->getPath());
if(strpos($currdir, '.') == false){
$test = strcmp($currdir, $prevdir);
if($test){
echo "current dir changing: ", $currdir, "\n";
$prevdir = $currdir;
}
}
}
}
}
test('fold');
?>
What I get from that is the following:
current dir changing: /Users/<usr>/Desktop/test/fold
current dir changing: /Users/<usr>/Desktop/test/fold/a
current dir changing: /Users/<usr>/Desktop/test/fold/a/b
current dir changing: /Users/<usr>/Desktop/test/fold
current dir changing: /Users/<usr>/Desktop/test/fold/one
current dir changing: /Users/<usr>/Desktop/test/fold/one/two
...But I only want the unique directories.
It's perhaps the method of object comparison in the loop that returns duplicates, as the iterator moves up and down the directory tree as it parses through folders.
The following worked for me. I also use array_unique() confirm no dupes as a redundancy.
$dirArray = []; // the array to store dirs
$path = realpath('/some/folder/location');
$objects = new RecursiveIteratorIterator(
new RecursiveDirectoryIterator($path),
RecursiveIteratorIterator::SELF_FIRST
);
// loop through all objects and store names in dirArray[]
foreach($objects as $name => $object){
if ($object->isDir()) {
$dirArray[] = $name;
}
}
// make sure there are no dupes
$result = array_unique($dirArray);
// print array out
print_r($result);
Is there a way to start from a different file eg. one that starts with "M" rather than with the very first file in a directory when iterating thru it (including sub-directories) with the following code?:
$filename = "/Users/jMac-NEW/Desktop";
$it = new RecursiveDirectoryIterator($filename, RecursiveDirectoryIterator::SKIP_DOTS);
foreach (new RecursiveIteratorIterator($it) as $file) { ...
Your RecursiveDirectoryIterator is a recursive iterator so you need to wrap that in a RecursiveIteratorIterator to traverse through subdirectories.
You can then filter that with a RegexIterator creating a pattern to filter out those files that you don't want to begin with.
$filename = __DIR__;
$it = new RegexIterator(
new RecursiveIteratorIterator(
new RecursiveDirectoryIterator($filename, RecursiveDirectoryIterator::SKIP_DOTS)
),
sprintf('|^%s[^A-La-l].*$|', preg_quote($filename . DIRECTORY_SEPARATOR, '|')
);
var_dump(iterator_to_array($it));