looking for a word in multiple files in directories - php

I'm working on a searchmachine for my blog (http://iljalicious.net/suche/) and I'm sorry that the used language is not English on the website but I translated the code for you:
$lookingfor = $_POST['word'];
$lines = file('../archiv/2015/juli/eintraege.dat');
$found = false;
foreach($lines as $line)
{
if(strpos($line, $lookingfor) !== false)
{
$found = true;
echo $line;
}
}
if(!$found)
{
echo 'I found nothing, dood!';
}
Currently, the function is working perfectly, but only if it is looking for a word in one file ('http://iljalicious.net/archiv/2015/juli/eintraege.dat').
On my blog, I have such a file for every month and I want my searchmachine to look for a word in every file called 'eintraege.dat' in the directory '../archiv/' and subdirectories as '2015','2016' etc.
How can I solve this problem?
Greetings, iljalicious
****EDIT*****
Found another..kind of stupid solution:
The code is not translated, but is the same as above, the only thing I changed was:
From:
$lines = file('../archiv/2015/juli/eintraege.dat');
To:
$archiv = file('../suche/archiv.php');
And it worked.
$suchbegriff = $_POST[suchbegriff];
$archiv = file('../suche/archiv.php');
$gefunden = false;
foreach($archiv as $zeile)
{
if(strpos($zeile, $suchbegriff) !== false)
{
$gefunden = true;
echo $zeile;
}
}
if(!$gefunden)
{
echo '<div class="information">'.
'Alter, wonach hast du gesucht?<br>'.
'Mhm... Soso, <a>'. $_POST[suchbegriff].
'</a> also! '.
'Dein Ernst?<br>'.
'Als ob ich über sowas berichte O;'.
'</div>';
}

You can try using glob,
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.
Something similar to this:
$file_list = [];
foreach (glob("archive*/eintraege.dat") as $filename) {
$file_list[] = $filename;
}
$lookingfor = $_POST['word'];
foreach ($file_list as $file) {
$lines = $file;
$found = false;
foreach ($lines as $line) {
if (strpos($line, $lookingfor) !== false) {
$found = true;
echo $line;
}
}
if (!$found) {
echo 'I found nothing, dood!';
}
}
Note: glob work only with files hosted on your server.
So if you want to search from the root of your server, the function argument should be something like : /var/www/site/content/archieve/*/eintraege.dat
if you want to search in the same folder of your file:
*/eintraege.dat

Related

Sorting files in an array by the ocurrences of a word in it, php

I'm making a search bar that searches files in a directory that have the word searched, then I want it to be added to an array by order of which one has more times the word asked to the one with less.
I'm working on PHP this is my code:
<?php
if(isset($_POST['busqueda'])){
$variable = utf8_encode($_POST['busqueda']);
}
$Array1 = array();
foreach(glob("*.txt") as $filename) {
$contents = file_get_contents($filename);
if (strpos($contents, $variable)){
$Array1[] = $filename;
}
}
I don't know how to do it exactly, I think that I should use substr_count(file_get_contents($Array1[$position1])) or something like that but I'm unsure how to make the sorting system, can someone help me!
print_r($Array1);
for($var1=0; $var1<sizeof($Array1); $var1++){
echo "times on the file: ".$Array1[$var1]."<br>";
echo substr_count(file_get_contents($Array1[$var1]));
}
?>
You can use the substr_count itself. Then you need to use arsort to sort the array.
$Array1 = array();
foreach (glob("*.txt") as $filename) {
$contents = file_get_contents($filename);
if ( ($count = substr_count($contents, $variable)) ) {
$Array1[$filename] = $count;
}
}
arsort($Array1) ;
print_r($Array1);
foreach ($Array1 as $file => $count) {
echo "times on the file($file): $count <br>";
}
Bash (available on at least Linux and Mac operating systems) makes it extremely easy to accomplish your task, because you can call commands through PHP's exec function, assuming it is not disabled by an administrator. If you're on Windows, then this will probably not work, but most people are using Linux for a production environment, so I thought this answer would be worthy of posting.
The following function is taken from CodeIgniter's file helper and only serves to fetch an array of filenames from a specified directory. If you don't need a function like this because you are getting your filenames from somewhere else, just note that this function can include the full file path for each file, and that's why I used it.
function get_filenames($source_dir, $include_path = FALSE, $_recursion = FALSE)
{
static $_filedata = array();
if ($fp = #opendir($source_dir))
{
// reset the array and make sure $source_dir has a trailing slash on the initial call
if ($_recursion === FALSE)
{
$_filedata = array();
$source_dir = rtrim(realpath($source_dir), DIRECTORY_SEPARATOR).DIRECTORY_SEPARATOR;
}
while (FALSE !== ($file = readdir($fp)))
{
if (#is_dir($source_dir.$file) && strncmp($file, '.', 1) !== 0)
{
get_filenames($source_dir.$file.DIRECTORY_SEPARATOR, $include_path, TRUE);
}
elseif (strncmp($file, '.', 1) !== 0)
{
$_filedata[] = ($include_path == TRUE) ? $source_dir.$file : $file;
}
}
return $_filedata;
}
else
{
return FALSE;
}
}
Now that I can fetch an array of filenames easily, I'd do this:
/**
* Here you can see that I am searching
* all of the files in the script-library
* directory for the word "the"
*/
$searchWord = 'the';
$directory = '/var/www/htdocs/script-library';
$filenames = get_filenames(
$directory,
TRUE
);
foreach( $filenames as $file )
{
$counts[$file] = exec("tr ' ' '\n' < " . $file . " | grep " . $searchWord . " | wc -l");
}
arsort( $counts );
echo '<pre>';
print_r( $counts );
echo '</pre>';
For a good explaination of how that works, see this: https://unix.stackexchange.com/questions/2244/how-do-i-count-the-number-of-occurrences-of-a-word-in-a-text-file-with-the-comma
I tested this code locally and it works great.

Php while inside for - What's wrong with this code?

This code is to read contents of a text file that contains 100 urls one in each line. The script is to search for a particular word in the urls using file_get_contents.
<?php
$mysearch = file("phpelist.txt");
for($index = 0; $index <count($mysearch); $index++)
{ while ($index >=10 && $index <=20 ):
$mysearch[$index] = str_replace("\n", "", $mysearch[$index]);
$data = file_get_contents("$mysearch[$index]");
$searchTerm = 'about';
if (stripos($data, $searchTerm) !== false) {
echo "$mysearch[$index]</strong>...FOUND WORD<br><strong>";
}
else
{
echo "$mysearch[$index]</strong>...NO SUCH WORD<br><strong>";
}
endwhile;
}
?>
Your code confused me. Looking at just the requirements statement, I got ...
$searchTerm = 'about';
$file = new SplFileObject('phpelist.txt');
foreach ($file as $n => $url) {
if ($n < 10) continue;
if ($n > 20) break;
$content = file_get_contents($url);
if (stripos($content, $searchTerm) !== false) {
echo "<strong>$url</strong>...FOUND WORD<br>";
} else {
echo "<strong>$url</strong>...NO SUCH WORD<br>";
}
}
CORRECTED: Additional requirements (see comments below). Which means its no longer much short than OP. The only thing it adds, I guess, is the use of SplFileObject. I like using SplFileObject because it lets you use a file like an array (without loading the entire file into memory) and so can be used in a foreach (since SplFileObject implements the Iterator interface).

PHP - get single file based on user

I'm having trouble getting my code to work the way I want.
I'm using scandir to get all files from the directory. This gives me a list with pdf files linked to a product, but the problems comes with the posibllity of pdf files multiple languages. Like so:
1096_EN.pdf
867_PT.pdf
914_EN.pdf
914_NL.pdf
Before _ is ID and after language. And I want the user to only see one file per product.
my code looks likes this:
$files = scandir($dir);
foreach ($files as $file)
{
$exp_file = explode("_", $file);
// check file for given ID
if($exp_file[0] == $_GET['iD']){
// check file for userlanguage
if($exp_file[1] == $lang){
echo $file;
}
// check file in english
elseif($exp_file[1] == "EN"){
echo $file;
}
// return available file in other language
else{
echo $file;
}
}
}
In case of 914 and NL the code returns two files. In case of 914 and PT i only get 1 file, 914_EN.pdf and in case of 867 and NL there will be zero files.
What is the best way to filter my files and return the best matched file? I personally think the error is in the for loop, but I cant find a proper way out..
thanks
If you want to have just the single items, you should keep a backlog of which you have already processed, as the foreach loop will go from for example 914_EN.pdf to 914_NL.pdf, while the checks have already been completed for 914_EN.pdf, so when you get to 914_NL.pdf, it just reruns the checks and thinks it is okay.
if working with multiple same values, you can first cleanse the array to get what you wanted. You can take a look at this, if this what you want. Cheers!
$files = array("1096_EN.pdf", "867_PT.pdf", "914_EN.pdf", "914_NL.pdf");
$new_exp_file = array();
foreach ($files as $file) {
$exp_file = explode("_", $file);
$new_exp_file[] = $exp_file[0];
}
$new_exp_file_arr_ = array_values(array_unique($new_exp_file));
for($i = 0, $file_ctr = count($new_exp_file_arr_); $i < $file_ctr; $i++) {
if($new_exp_file_arr_[$i] == "914") {
echo $new_exp_file_arr_[$i] . "<br>";
echo "<ul>";
foreach ($files as $file) {
$exp_file = explode("_", $file);
if($new_exp_file_arr_[$i] == $exp_file[0]) {
echo "<li>" . $exp_file[1] . "</li>";
}
}
echo "</ul>";
}
}
this seems to work for me? Using a regex probably not as efficient as the above methods though.
$_GET['iD'] = 1096;
$ptn = "^((\d+)\_([a-zA-Z]+)\.([a-zA-Z]+))^";
$aFiles = array('1096_EN.pdf','867_PT.pdf','914_EN.pdf','914_NL.pdf');
$lang = "EN";
foreach ($aFiles as $sFileName)
{
preg_match($ptn, $sFileName, $aFileParts);
var_dump($aFileParts);
// check file for given ID
if($aFileParts[2] == $_GET['iD']){
// check file for userlanguage
if(strtolower($aFileParts[3]) == strtolower($lang)){
echo $sFileName;
break;
}
// return available file in other language
else{
echo $sFileName;
}
}
}
I've solved my problem by the following:
if(glob($_GET['iD']."_".$_GET['t']."*.pdf"))
{
$file = glob($_GET['iD']."_".$_GET['t']."*.pdf");
echo $file[0];
}
else
{
if(glob($_GET['iD']."_EN*.pdf"))
{
$file = glob($_GET['iD']."_EN*.pdf");
echo $file[0];
}
else
{
$file = glob($_GET['iD']."*.pdf");
echo $file[0];
}
}
No more looping, just checking for different files with wildcards. Works like a charm. I.m.o. much cleaner with larger lists of files..

PHP - Get directory contents and info and output array

I'm working on the following but have become stumped as to how to get this to output.
I have the following which scans the directory contents, then gets the info and saves it as an array:
//SCAN THE DIRECTORY
$directories = scandir($dir);
$directinfo = array();
foreach($directories as $directory){
if ($directory === '.' or $directory === '..') continue;
if(!stat($dir.'/'.$directory)){
} else {
$filestat = stat($dir.'/'.$directory);
$directinfo[] = array(
'name' => $directory,
'modtime' => $filestat['mtime'],
'size' => $filestat['size']
);
}
}
When trying to output it however, I'm just getting single letters with a lot of breaks. Im obviously missing something here with the output loop.
foreach($directinfo as $dirInfo){
foreach($dirInfo as $drInfo){
for ($x=0; $x<=2; $x++) {
<span>"".$drInfo[$x]."<br/></span>";
}
}
}
Help is greatly appreciated. :)
You have already did everything just remove your for loop.
and try to do the following-
foreach($directinfo as $dirInfo){
foreach($dirInfo as $key=>$drInfo){
echo "<span>".$key."=>".$drInfo."<br/></span>";
}
}
I think your dealing with a 2d array, but treating it like a 3d array.
what does
foreach($directinfo as $dirInfo){
foreach($dirInfo as $drInfo){
var_dump($drInfo);
}
}
give you?
You're building a single array, dirInfo.
Php foreach takes the array first;
foreach($dirInfo as $info) {
echo "<span>" . $info['name'] . "</span>";
}
Try this function. It will return you list of all files with path.
// to list the directory structure with all sub folders and files
function getFilesList($dir)
{
$result = array();
$root = scandir($dir);
foreach($root as $value) {
if($value === '.' || $value === '..') {
continue;
}
if(is_file("$dir$value")) {
$result[] = "$dir$value";
continue;
}
if(is_dir("$dir$value")) {
$result[] = "$dir$value/";
}
foreach(getFilesList("$dir$value/") as $value)
{
$result[] = $value;
}
}
return $result;
}

How to parse a .plist file with php?

Can i parse a plist file with php and kind of get it into an array, like the $_POST[''] so i could call $_POST['body'] and get the string that has the <key> body ?
CFPropertyList - A PHP Implementation Of Apple's plist (PropertyList)
Googling for "php plist parser" turned up this blog post that seems to be able to do what you are asking for.
Took a look at some of the libraries out there but they have external requirements and seem overkill. Here's a function that simply puts the data in to associative arrays. This worked on a couple of exported itunes plist files I tried.
// pass in the full plist file contents
function parse_plist($plist) {
$result = false;
$depth = [];
$key = false;
$lines = explode("\n", $plist);
foreach ($lines as $line) {
$line = trim($line);
if ($line) {
if ($line == '<dict>') {
if ($result) {
if ($key) {
// adding a new dictionary, the line above this one should've had the key
$depth[count($depth) - 1][$key] = [];
$depth[] =& $depth[count($depth) - 1][$key];
$key = false;
} else {
// adding a dictionary to an array
$depth[] = [];
}
} else {
// starting the first dictionary which doesn't have a key
$result = [];
$depth[] =& $result;
}
} else if ($line == '</dict>' || $line == '</array>') {
array_pop($depth);
} else if ($line == '<array>') {
$depth[] = [];
} else if (preg_match('/^\<key\>(.+)\<\/key\>\<.+\>(.+)\<\/.+\>$/', $line, $matches)) {
// <key>Major Version</key><integer>1</integer>
$depth[count($depth) - 1][$matches[1]] = $matches[2];
} else if (preg_match('/^\<key\>(.+)\<\/key\>\<(true|false)\/\>$/', $line, $matches)) {
// <key>Show Content Ratings</key><true/>
$depth[count($depth) - 1][$matches[1]] = ($matches[2] == 'true' ? 1 : 0);
} else if (preg_match('/^\<key\>(.+)\<\/key\>$/', $line, $matches)) {
// <key>1917</key>
$key = $matches[1];
}
}
}
return $result;
}

Categories