Iterate thru possible file extension to get the proper extension - php

I have a folder with many files in various formats eg .jpg, .png, .pdf, .doc etc... The files are on a remote server. I have a json file with list of filenames and its location but missing the extensions.
I want to rebuild the json file and add the proper extension to filename. How can I do this with php? Can anyone give me any ideas how to iterate thru possible extensions to get the right filename + ext on the server.
eg. I have a url like this - http://www.somesite.com/filename. I know on the server the file is pdf but how can I do this programatically for many files which may be different and rename the url?
Any ideas?

Use a For Loop To loop over all current know file extensions and execute a GET request to the $url . $extension and see if the server returns a file.
If the server returns a file, you can break the for loop.
You can nest 2 for loops in each other to do this far all know urls.
Example
$files = [
"http://test.com/test",
"http://test.com/test2"
];
$extensions = [
".jpg",
".docx"
];
foreach ($files as $file)
{
foreach ($extensions as $extension)
{
$foundFile = // Get requests here
if(FILE_IS_FOUND){
// Store file where ever you need it
break;
}
}
}
This example uses a Foreach Loop

Related

Remove files which have not filename duplicates

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

How to find missing .mp4 files in a directory?

I have files likes this on my server:
aaaa.flv
aaaa.mp4
bbbb.flv
bbbb.mp4
cccc.flv
dddd.flv
dddd.mp4
This code isn't working:
$dir=$_SERVER{'DOCUMENT_ROOT'}."/test/";
foreach(glob($dir . "*.flv") as $file)
{
$strip_ext=substr($file, 0, strrpos($file, "."));
$mp4_ext=$strip_ext.".mp4";
if (!file_exists($dir . $mp4_ext)) {
echo "Non-matching pair! ".$strip_ext."<BR>";
}
}
How can I find my .flv files that don't have a matching .mp4?
I'd prefer to put a script in the directory and run it and have it spit out all the filenames without matching .mp4's, this would tell me files that I'll need to convert.
Rather than doing iterated directory checks for if a given .mp4 file exists, I'd rather try (and see if it chokes):
extracting all of the .flv files
extracting all of the .mp4 files
isolate the missing .mp4 files
start converting
Code: (Mock Demo)
chdir($_SERVER{'DOCUMENT_ROOT'}."/test/"); // change working directory so that glob's output excludes the path
$flvs=array_map(function($f){return basename($f,'.flv');},glob("*.flv")); // store .flv's and strip suffixes
$mp4s=array_map(function($f){return basename($f,'.mp4');},glob("*.mp4")); // store .mp4's and strip suffixes
$need_conversion=array_diff($flvs,$mp4s); // run ffmpeg() on these suffix-free files
// $need_conversion = array( 4 => 'cccc' )

How to find file without specific file extension in laravel storage?

How to find file by name without specific extension in laravel Storage?
like this "filename.*"
Storage::get("filename.*")
I tried this but seems not to work. It searches for specific file with specific extension.
Storage::get() takes a file path as a parameter and returns the content of a single file identified by this path or throws FileNotFoundException if file can't be found.
Wildcards are not supported in the path - one reason for that could be that there might be multiple files that match the path with wildcards which would break the rule that content of a single file is returned from Storage::get(). Scanning the whole folder would also be much slower, especially with remote storages.
However, you could get what you want using other functionality that Storage facade offers. First, list the content of your storage - that will give you the list of all available files. Then filter the list yourself to get the list of matching files.
// list all filenames in given path
$allFiles = Storage::files('');
// filter the ones that match the filename.*
$matchingFiles = preg_grep('/^filename\./', $allFiles);
// iterate through files and echo their content
foreach ($matchingFiles as $path) {
echo Storage::get($path);
}
Accepted solution works. However I've found this other and I like it more:
$matchingFiles = \Illuminate\Support\Facades\File::glob("{$path}/*.log");
See reference here:
http://laravel-recipes.com/recipes/143/finding-files-matching-a-pattern
Minor change to jedrzej.kurylo's answer and combining wogsland's answer using laravel 8:
'/^filename\./' or '/filename\./' pattern does not work in my case.
// From:
$matchingFiles = preg_grep('/^filename./', $allFiles);
// To:
$allFiles = Storage::disk('yourStorageDisk')->files('folder/path');
$allowedMimeTypes = ['image/jpeg', 'image/png', 'image/webp'];
$matchingFiles = preg_grep('{'.$image.'}', $allFiles);
foreach ($matchingFiles as $path) {
// get real mime type
$contentType = image_type_to_mime_type(exif_imagetype(asset($path)));
// compare it with our allowed mime types
if (in_array($contentType, $allowedMimeTypes)) {
// do something here...
}
}
This way we can fetch files or images safely.
Dont trust what you see. Get inside and get the ext for your file
$pic = 'url/your.file';
$ext = image_type_to_mime_type(exif_imagetype($pic));
$ext = explode('/',$ext);
echo $ext[1];

PharData offsetExists on filename prefixed with ".\"

I have a .tar.gz file downloaded from an external API which we have to implement. It contains images for an object.
I'm not sure how they managed to compress it this way, but the files are basically prefixed with the "current directory". It looks like this in WinRAR:
And like this in 7-Zip, note the .tar first level, and "." second level:
-> ->
When calling
$file = 'archive.tar.gz';
$phar = new PharData($file, FilesystemIterator::CURRENT_AS_FILEINFO);
var_dump($phar->offsetGet('./12613_s_cfe3e73.jpg'));
I get the exception:
Cannot access phar file entry '/12613_s_cfe3e73.jpg' in archive '{...}/archive.tar.gz'
Calling a file which does not exist, e.g.:
var_dump($phar->offsetGet('non-existent.jpg'));
Or calling it without the directory seperator, e.g.:
var_dump($phar->offsetGet('12613_s_cfe3e73.jpg'));
I get a
Entry 12613_s_cfe3e73.jpg does not exist
Exception.
It is not possible to get the archive formatted differently. Does anyone have an idea how to solve this?
Ended up using Archive_Tar. There must be something wrong in the source code of PHP, though I don't think this is the "normal" way of packaging a .tar either.
Unfortunately I'm not very good at C, but it's probably in here (line 1214) or here.
This library seems to handle it just fine, using this example code:
$file = 'archive.tar.gz';
$zip = new Archive_Tar($file);
foreach ($zip->listContent() as $file) {
echo $file['filename'] . '<br>';
}
Result:
./12613_s_f3b483d.jpg
./12613_s_cfe3e73.jpg
./1265717_s_db141dc.jpg
./1265717_s_af5de56.jpg
./1265717_s_b783547.jpg
./1265717_s_35b11f9.jpg
./1265716_s_83ef572.jpg
./1265716_s_9ac2725.jpg
./1265716_s_c5af3e9.jpg
./1265716_s_c070da3.jpg
./1265715_s_4339e8a.jpg
Note the filenames are still prefixed with "./" just like they are in WinRAR.
If you want to stick to using PharData, i suggest a more conservative, two-step approach, where you first decompress the gz and then unarchive all files of the tar to a target folder.
// decompress gz archive to get "/path/to/my.tar" file
$gz = new PharData('/path/to/my.tar.gz');
$gz->decompress();
// unarchive all files from the tar to the target path
$tar = new PharData('/path/to/my.tar');
$tar->extractTo('/target/path');
But it looks like you want to select individual files from the tar.gz archive directly, right?
It should work using fopen() with a StreamReader (compress.zlib or phar) and selecting the individual file. Some examples:
$f = fopen("compress.zlib://http://some.website.org/my.gz/file/in/the/archive", "r");
$f = fopen('phar:///path/to/my.tar.gz//file/in/archive', 'r');
$filecontent = file_get_contents('phar:///some/my.tar.gz/some/file/in/the/archive');
Streaming should also work, when using Iterators:
$rdi = new RecursiveDirectoryIterator('phar:///path/to/my.tar.gz')
$rii = new RecursiveIteratorIterator($rdi, RecursiveIteratorIterator::CHILD_FIRST);
foreach ($rii as $splFileInfo){
echo file_get_contents($splFileInfo->getPathname());
}
The downside is that you have to buffer the stream and save it to file.
Its not a direct file extraction to a target folder.

Select file(s) in a directory based upon complex filename

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;
}

Categories