I have /fonts/ folder full of .js files.
I know how to read this folder and list all the files there:
$dir = "/fonts";
if (is_dir($dir)) {
if ($dh = opendir($dir)) {
while (($file = readdir($dh)) !== false) {
echo '<tr><td>'. $file .'</td></tr>';
}
closedir($dh);
}
}
But I don't want to write filenames but data they store.
The pattern inside looks like this:
NameOfTheFontFile_400_font.js:
(...) "font-family":"NameOfTheFont" (...)
So how to modify my first script to open-read each file and grab the font-family name instead of file name?
Thanks a lot!
You could use readfile() to echo it's output. Also note that this is not tested, but it should work:
$dir = "/fonts";
if (is_dir($dir)) {
if ($dh = opendir($dir)) {
while (($file = readdir($dh)) !== false) {
echo '<tr><td>';
readfile($file);
echo '</td></tr>';
}
closedir($dh);
}
}
If your .js file has extra data beside the font name, you do do something like this to find the file name:
$dir = "/fonts";
if (is_dir($dir)) {
if ($dh = opendir($dir)) {
while (($file = readdir($dh)) !== false) {
$lines = file($file);
foreach ($lines as $line) {
if (preg_match('/("font-family":)(".+")/', $line, $parts) ) {
echo '<tr><td>', $parts[2], '</td></tr>';
}
}
}
closedir($dh);
}
}
Off-topic: Why are you storing the font's names inside .js files? It would be better to store them inside a xml file or in a DB, because that's what they are made for.
From the php manual:
$lines = file($file);
Edit: This can probably be optimized, but to get the line with the font:
foreach ($lines as $line)
{
if (strpos($line, 'font-family') !== false)
{
echo $line;
}
}
You can dig further in that line using string functions or regular expressions to get the exact font name (using for example strpos()), but how to do that depends on the general format of the file.
This does the job:
$dir = '/fonts';
$files = array_filter(glob("$dir/*"), 'is_file');
$contents = array_map('file_get_contents', $files);
foreach ($contents as $content) {
if (preg_match('#"font-family":"([^"]+)"#', $content, $matches)) {
echo '<tr><td>'.htmlspecialchars($matches[1]).'</td></tr>';
}
}
Or in a different style:
$files = glob("$dir/*");
foreach($files as $file) {
if (is_file($file)) {
$content = file_get_contents($file);
if (preg_match('#"font-family":"([^"]+)"#', $content, $matches)) {
echo '<tr><td>'.htmlspecialchars($matches[1]).'</td></tr>';
}
}
}
From the documentation - http://www.php.net/manual/en/function.file-get-contents.php , you can use file_get_contents to get the contents of files using the filenames you got from directory listing.
string file_get_contents ( string$filename [, bool$use_include_path = false [, resource $context [, int $offset = 0 [, int $maxlen ]]]] )
NOTE: Others have already answered the question in detail. Edited this answer in response to sel-fish's comment to elaborate on the linked documentation.
Related
I would like to know how can I (recursively) scan a directory files (100+) looking for a preg_match() in files contents. I'm looking if any file contains a backtick (`).
Thanks for your answers.
you can do it, using php function opendir try this function :
<?php
function findbacktick ($dir){
// Open a known directory, and proceed to read its contents
if (is_dir($dir)) {
if ($dh = opendir($dir)) {
while (($file = readdir($dh)) !== false) {
preg_match("/'/", $file, $matches);
if (count($matches)>=1) {
echo 'file contains a backtick : '.$file.'</br>-----</br>';
}
}
closedir($dh);
}
}
}
$dir = "path/to/dir";
findbacktick ($dir);
?>
You can wrap glob in recursive function. I'm giving you the idea with following basic version of it.
function find_files($dir, $files = []) {
foreach (glob($dir."/*") as $file) {
if(is_dir($file)) {
$files = find_files($file, $files);
}
$content = file_get_contents($dir."/".$file);
if(preg_match('/[YOUR_PATTERN]/', $content)) {
$files[] = $file;
}
}
return $files;
}
I haven't tried it, but I guess it should work.
PS. It might give you the memory exhausted error or timeout error.
For the below code I have multiple directories and files. I can display one filename per directory(Which is good with the "BREAK").
<?php
$dir = "/images/";
$i=0;
// Open a directory, and read its contents
if (is_dir($dir)){
if ($dh = opendir($dir)){
while (($file = readdir($dh)) !== false){
echo "filename:" . $file . "<br>";
break;
//---- if ($i>=5) { break; }
}
closedir($dh);
}
}
?>
With
if ($i>=5) { break; } I can still display 5 filenames but it reads only one directory.
I want to display at least 5 file names from all directories, how can I do it?
Use the scandir function.
array scandir ( string $directory [, int $sorting_order = SCANDIR_SORT_ASCENDING [, resource $context ]] )
or
If you are using unix you could also do a system call and run the following command.
ls /$dir | head -5
$dir is the directory and -5 is the number filenames in the directory.
Since you said that you have multiple directory's, I rewrote your code a bit:
(Here I first loop through all directory's with array_map() then I get all files from each directory with glob(). After this I just limit the files per directory with array_slice() and at the end I simply print all file names)
<?php
$directorys = ["images/", "xy/"];
$limit = 3;
//get all files
$files = array_map(function($v){
return glob("$v*.*");
}, $directorys);
//limit files per directory
$files = array_map(function($v)use($limit){
return array_slice($v, 0, $limit);
}, $files);
foreach($files as $directory) {
echo "<b>Directory</b><br>";
foreach($directory as $file)
echo "$file<br>";
echo "<br><br>";
}
?>
You don't have to break it, you can just skip it. And in doing so, you have to use continue instead.
$dir = "/images/";
$i=0;
// Open a directory, and read its contents
if (is_dir($dir)){
if ($dh = opendir($dir)){
while (($file = readdir($dh)) !== false){
echo "filename:" . $file . "<br>";
if ($i>=5)
continue;
}
closedir($dh);
}
}
Here is also another scenario. Because you mentioned that you have many directories but you only show one main directory, I am guessing that the directories you've mentioned were inside the /images/ directory.
$dir = "images/";
$i=1;
// Open a directory, and read its contents
if (is_dir($dir)){
if ($dh = opendir($dir)){
while (($file = readdir($dh)) !== false){
$j=1;
if (is_dir($file)) {
if ($internalDir = opendir($file)) {
while (($internalFile = readdir($internalDir)) !== false) {
echo $file."->filename: ".$internalFile."<br>";
if ($j>=5)
continue;
$j++;
}
closedir(opendir($file));
}
} else {
echo "filename:" . $file . "<br>";
if ($i>=5)
continue;
$i++;
}
}
closedir($dh);
}
}
Read more about continue here: http://php.net/manual/en/control-structures.continue.php
Right now there is an upload system on the site I am working on where users can upload some documents to a particular file. Later on I will need to make these documents downloadable. Is there an easy way to iterate through all the files in a particular directory and create download links for the files?
Something like:
foreach($file){
echo 'somefilename';
}
Many thanks in advance.
if($dh = opendir('path/to/directory')) {
while(($file = readdir($dh)) !== false) {
if($file == "." || $file == "..") { continue; }
echo '' . $file . '';
}
closedir($dh);
}
You should see opendir.
Example from that page adapted to question:
$dir = "/etc/php5/";
$path = "/webpath";
// Open a known directory, and proceed to read its contents
if (is_dir($dir)) {
if ($dh = opendir($dir)) {
while (($file = readdir($dh)) !== false) {
echo "$file";
}
closedir($dh);
}
}
I have a directory with a lot of files inside:
pic_1_79879879879879879.jpg
pic_1_89798798789798789.jpg
pic_1_45646545646545646.jpg
pic_2_12345678213145646.jpg
pic_3_78974565646465645.jpg
etc...
I need to list only the pic_1_ files. Any idea how I can do?
Thanks in advance.
Use the glob() function
foreach (glob("directory/pic_1_*") as $filename) {
echo "$filename";
}
Just change directory in the glob call to the proper path.
This does it all in one shot versus grabbing the list of files and then filtering them.
The opend dir function will help you
$dir ="your path here";
$filetoread ="pic_1_";
if (is_dir($dir)) {
if ($dh = opendir($dir)) {
while (($file = readdir($dh)) !== false) {
if (strpos($file,$filetoread) !== false)
echo "filename: $file : filetype: " . filetype($dir . $file) . "\n";
}
closedir($dh);
}
}
good luck see php.net opendir
This is what glob() is for:
glob — Find pathnames matching a pattern
Example:
foreach (glob("pic_1*.jpg") as $file)
{
echo $file;
}
Use scandir to list all the files in a directory and then use preg_grep to get the list of files which match the pattern you are looking for.
This is one of the samples from the manual
http://nz.php.net/manual/en/function.readdir.php
<?php
if ($handle = opendir('.')) {
while (false !== ($file = readdir($handle))) {
if ($file != "." && $file != "..") {
echo "$file\n";
}
}
closedir($handle);
}
?>
you can modify that code to test the filename to see if it starts with pic_1_
using something like this
if (substr($file, 0, 6) == 'pic_1_')
Manual reference for substr
http://nz.php.net/manual/en/function.substr.php
I have a number of text files held in directory
/results/...
All the text files are named with unixtime stamps, inside each of the following files there is:
#text¬test¬test1¬test2¬test3¬test4¬1262384177
Each piece of text is seperated by '¬'.
I'd then like to feed the contents of the text file into an array and output it, in for example a table, but for each of the files (Perhaps loop-like?)
If have this but it only works for one file and fixed file name:
$filename = "results/unixtime.txt";
$handle = fopen($filename, "r");
$contents = fread($handle, filesize($filename));
fclose($handle);
$array01 = explode("¬",$contents);
$count = count($array01);
echo "<table width = 500 border=1 cellpadding=4>";
$i=0;
for ($i=0;$i<$count;$i++) {
echo "<tr><td>";
echo $array01[$i];
echo "</td></tr>";
}
echo "</table>";
I suggest the fairly-unknown glob function to detect all your files. Then with all the filenames in a handy array, just iterate through and open up/read each one. Sort of like this:
$files = glob('*.txt');
while(list($i, $filename) = each($files)){
//what you have now
}
A couple of things:
Unless you're dealing with really large files just use file_get_contents() to load files. It's a one-liner versus three lines of code that you just don't need;
Loop over arrays using foreach unless you explicitly need a loop counter. The loop condnition/counter is just another area where you can make simple errors;
Use opendir(), readdir() and closedir() for reading directory contents; and
Directories will contain entries like "." and "..". Use filetype() and/or a check on the name and/or extension to limit it to the files you're interested in.
Example:
$directory = "results/";
$dir = opendir($directory);
while (($file = readdir($dir)) !== false) {
$filename = $directory . $file;
$type = filetype($filename);
if ($type == 'file') {
$contents = file_get_contents($filename);
$items = explode('¬', $contents);
echo '<table width="500" border="1" cellpadding="4">';
foreach ($items as $item) {
echo "<tr><td>$item</td></tr>\n";
}
echo '</table>';
}
}
closedir($dir);
You can get all the files located in "result" via opendir.
There is also an example ...
<?php
$dir = "/etc/php5/";
// Open a known directory, and proceed to read its contents
if (is_dir($dir)) {
if ($dh = opendir($dir)) {
while (($file = readdir($dh)) !== false) {
echo "filename: $file : filetype: " . filetype($dir . $file) . "\n";
}
closedir($dh);
}
}
?>
Grab the files in the directory and read each filename.
<?php
if ($handle = opendir('.')) {
while (false !== ($file = readdir($handle))) {
if ($file != "." && $file != "..") {
$filename = $file;
//your code
}
}
closedir($handle);
}
?>
source: http://php.net/manual/en/function.readdir.php
Here is a more elegant way of writing brianreavis solution, also use file_get_contents instead of fopen, fread and fclose, it's faster and less verbose.
foreach (glob('*.txt') as $filename)
{
$contents = file_get_contents($filename);
}
Use this code, replace DOCROOT with directory you want to scan.
foreach (scandir(DOCROOT.'css') as $dir) {
echo $dir . "<br>";
echo file_get_contents(DOCROOT . 'css/' . $dir ) . "<hr />";
}