http://php.net/glob
The documentation page on glob() has this example:
<?php
foreach (glob("*.txt") as $filename) {
echo "$filename size " . filesize($filename) . "\n";
}
?>
But to be honest, I don't understand how this can work.
The array produced by glob("*.txt") will be traversed, but where does this array come from? Is glob() reading a directory? I don't see that anywhere in the code. Glob() looks for all matches to *.txt
But where do you set where the glob() function should look for these strings?
Without any directory specified glob() would act on the current working directory (often the same directory as the script, but not always).
To make it more useful, use a full path such as glob("/var/log/*.log"). Admittedly the PHP documentation doesn't make the behaviour clear, but glob() is a C library function, which is where it originates from.
Something useful I've discovered with glob(), if you want to traverse a directory, for example, for images, but want to match more than one file extension, examine this code.
$images = glob($imagesDir . '*' . '.{jpg,jpeg,png,gif}', GLOB_BRACE);
The GLOB_BRACE flag makes the braces sort of work like the (a|b) regex.
One small caveat is that you need to list them out, so you can't use regex syntax such as jpe?g to match jpg or jpeg.
Yes, glob reads the directory. Therefore, if you are looking to match files in a specific directory, then the argument you supply to glob() should be specific enough to point out the directory (ie "/my/dir/*.png"). Otherwise, I believe that it will search for files in the 'current' directory.
Note that on some systems filenames can be case-sensitive so "*.png" may not find files ending in ".PNG".
A general overview of its purpose can be found here. Its functionality in PHP is based on that of the libc glob function whose rationale can be read at http://web.archive.org/web/20071219090708/http://www.isc.org/sources/devel/func/glob.txt .
Related
I have a PHP program which scans a folder named output (which contains all image files in any format) for images. The image files are the screenshots of the output in terminal (I'm using Linux) of various Java programs. The image files are named according to the class name in which the main() function resides. So for example if the main() function resides inside the public Example class, then the output screenshot will be named Example with the extension of either .jpg, .jpeg, .png or .gif. The PHP program has a front page which scans for Java files and lists them in an unordered list with links the user can click to go on the next page. The next page reads the particular file and displays the source code along with the output screenshot. Now since I'm using Fedora and Fedora takes screenshots in png format, that is quite easy like:
echo '<img src="' . $file_name . '".png>'
But what if someone uploads a Java program with the output screenshot in any format? (jpg, jpeg, png, gif). How to then load the appropriate image file since I don't know what the extension will be?
I have an answer to use foreach loop and read through every image file there is within the output folder and then use an if condition for checking the appropriate file names with the various extensions but I think it will not be a very good programming practice.
I generally try to avoid conditions while programming and use more mathematical approach cause that gives me the challenge I need and I feel my code looks different and unique compared to others' but I don't seem to make it work this time.
I'm feeling that this can be done using regular expressions but I don't know how to do it. I know regular expressions but I'm clueless to even how to use them for this. Any answer to not use regular will be appreciated but I want to make this work using regular expressions because in that way I'll also add a little bit of knowledge to my regular expression concepts.
Thanks.
Here's an alternative to MM's that uses RegEx:
function getImageFilename ($basename, $directory) {
$filenames = scandir($directory);
$pattern = "/^" . $basename . "\.(jpeg|png|jpg|gif)$/";
foreach($filenames as $filename) {
preg_match($pattern, $filename, $matches);
if($matches) {
return $filename;
}
}
return false;
}
You can't avoid using a loop. You either loop through the possible file names and check for their existence, or you get a list of all the files in the directory and loop through them whilst performing a pattern match.
If there aren't a lot of files in the directory then this function might perform better because it only needs to call the OS once (to get a list of the files in the directory), whereas asking the OS to check for file existence multiple times requires multiple system calls. (I think that's right...)
One possible solution, you could check if the file exists with that extension (assuming you won't have multiple images with the same name but different extensions):
function get_image($file_name) {
if (file_exists($file_name . '.png')) {
return $file_name . '.png';
} elseif (file_exists($file_name . '.jpg')) {
return $file_name . '.jpg';
} elseif (file_exists($file_name . '.gif')) {
return $file_name . '.gif';
}
return false;
}
echo '<img src="' . get_image($file_name) . '">';
You define the pattern as an or list of the various extensions:
$pattern = '/\.(jpg|png|gif)$/i';
We are also making sure this is an extension by including the match with a dot (escaped) and making sure it's at the end of the string ($). The "i" at the end of that enables case-insensitive matching, so that the regex still picks up GIF or JPG in filenames.
After that, the test is fairly simple:
if (preg_match($pattern, $filename)) {
echo "File $filename is an image";
}
Putting it together in an example, you can see:
$filename = 'test.png';
$pattern = '/\.(jpg|png|gif)$/i';
if (preg_match($pattern, $filename)) {
echo "File $filename is an image";
}
https://eval.in/618651
Whether you want to wrap that in a function, is up to you, as you would have to decide what to return in case the filename does not match one of the extensions provided.
Also note that the test is based on the extension only and not on the content.
I am using the following code to display the files in descending order of date. But When I upload any file without extension its not visible because of glob, is there any way to show the hidden files?
Code:
<?php
$dir = "/opt/lampp/htdocs/jquery";
chdir($dir);
array_multisort(array_map('filemtime', ($files = glob("*.*"))), SORT_DESC, $files);
foreach($files as $filename)
{
echo "<li>".$filename."</li>";
}
?>
#bodi0 gave you the code for ONLY items with no dots, you might be looking for
...glob("*")
to get all files.
Then, you will need to remove "." and ".."
This is impossible with inclusive only glob (python), the answerers (is that a word), misunderstood your question.
/* gets all files/folders and returns folders with no "/" at the end, /*/ gets only folders and adds the "/" at the end, but for files with NO extension ie path/foo (NO DOT) it is not straightforward to separate the files from the folders with glob.
It is possible, of course, just pass this regex pattern to the glob():
glob("([^\.])");
The pattern ([^\.]) means every file name, which does not have a dot in it.
I have a bunch of uniquely named images with different extensions, if I have one of the unique names, but I don't know the extension (it's an image extension), how can I find the image extension as fast as possible? I've seen other people doing this by searching all possible file extensions on that file name, but it seems too slow to try and load 6 different possible combinations before bringing up the original image.
Does anyone know an easier way?
You could use glob for this. Might not be the best solution but it is simple;
The glob() function searches for all the pathnames matching pattern
according to the rules used by the libc glob() function, which is
similar to the rules used by common shells.
$files = glob('filenamewithoutextension.*');
if (sizeof($files) > 0) {
$file = $files[0]; // Might be more than one hit however we are only interested in the first one?
}
After getting the filename you can use pathinfo to get the specific extension.
$extension = pathinfo($file, PATHINFO_EXTENSION);
I'd like to be able to select a file by just giving it's name (without extension). For example, I might have a variable $id holding 12. I want to be able to select a file called the-id-in-the-variable, say, 12.png from a directory, but it may have any one of a number of file extensions, listed below:
.swf
.png
.gif
.jpg
There is only one occurrence of each ID. I could use a loop and file_exists(), but is there a better way?
Thanks,
James
$matches = glob("12.*");
would return an array with all the matching filenames in the current directory. glob() works much the same as wildcard matching at the shell prompt.
Take a look at glob. Unfortunately, the exact semantics of the $pattern parameter is not described in the manual. But it seems your problem can be solved using this function.
Quick question to OP here:
What is the file extension of this file: somefile.tar.gz? Is it .gz or .tar.gz? :) I ask because most would answer this question as .tar.gz...
I have a huge repository of files that are ordered by numbered folders. In each folder is a file which starts with a unique number then an unknown string of characters. Given the unique number how can i open or copy this file?
for example:
I have been given the number '7656875' and nothing more.
I need to interact with a file called '\server\7656800\7656875 foobar 2x4'.
how can i achieve this using PHP?
If you know the directory name, consider using glob()
$matches = glob('./server/dir/'.$num.'*');
Then if there is only one file that should start with the number, take the first (and only) match.
Like Yacoby suggested, glob should do the trick. You can have multiple placeholders in it as well, so if you know the depth, but not the correct naming, you can do:
$matchingFiles = glob('/server/*/7656875*');
which would match
"/server/12345/7656875 foo.txt"
"/server/56789/7656875 bar.jpg"
but not
"/server/12345/subdir/7656875 foo.txt"
If you do not know the depth glob() won't help, you can use a RecursiveDirectoryIterator passing in the top most folder path, e.g.
$iterator = new RecursiveIteratorIterator(
new RecursiveDirectoryIterator('/server'));
foreach($iterator as $fileObject) {
// assuming the filename begins with the number
if(strpos($fileObject->getFilename(), '7656875') === 0) {
// do something with the $fileObject, e.g.
copy($fileObject->getPathname(), '/somewhere/else');
echo $fileObject->openFile()->fpassthru();
}
}
* Note: code is untested but should work
DirectoryIterator return SplFileInfo objects, so you can use them to directly access the files through a high-level API.
$result = system("ls \server\" . $specialNumber . '\');
$fh = fopen($result, 'r');
If it's hidden below in sub-sub-directories of variable length, use find
echo `find . -name "*$input*"`;
Explode and trim each result, then hope you found the correct one.