I basically want to search for a file on my computer. I know how to search but is there a fast way of searching a name and an extension without flooding my script with more than 2 for loops? the names (eg.. file,virus,node,misc) and the extensions will be added dynamically, Not through the source code.. the names will be in the thousands so i dont want to add them one by one, hence why i am doing it dynamically.
i was thinking:
foreach($names as $i){
if (file_exists($i.".exe" | $i.".py" | $i.".js" | $i.".html" | )){
//echo true or false}}
Like i said. I will be adding in extensions dynamically also. Would it be worth it having the code long with file_exists(20 thousand extensions) or just add them with a form?
Would it be a for loop inside another for loop?
If your code is on a linux server and you have the program 'locate', I would consider using that instead. It will save you a lot of load on your server and will return results a lot faster.
There is a way using the Spl Iterators.
The following example is taken from the documentation of RecursiveDirectoryIterator. It searches for a file called 'Yourfile.py':
$filename = 'Yourfile.py';
$directory = new RecursiveDirectoryIterator('path/to/search_root/');
$iterator = new RecursiveIteratorIterator($directory);
$regexiterator = new RegexIterator(
$iterator,
'/^' . preg_quote($filename) . '$/',
RecursiveRegexIterator::GET_MATCH
);
foreach($regexiterator as $fileinfo) {
var_dump($fileinfo);
}
Related
The project I am working on requires creating .tar.gz archives and feeding it to an external service. This external service works only with .tar.gz so another type archive is out of question. The server where the code I am working on will execute does not allow access to system calls. So system, exec, backticks etc. are no bueno. Which means I have to rely on pure PHP implementation to create .tar.gz files.
Having done a bit of research, it seems that PharData will be helpful to achieve the result. However I have hit a wall with it and need some guidance.
Consider the following folder layout:
parent folder
- child folder 1
- child folder 2
- file1
- file2
I am using the below code snippet to create the .tar.gz archive which does the trick but there's a minor issue with the end result, it doesn't contain the parent folder, but everything within it.
$pd = new PharData('archive.tar');
$dir = realpath("parent-folder");
$pd->buildFromDirectory($dir);
$pd->compress(Phar::GZ);
unset( $pd );
unlink('archive.tar');
When the archive is created it must contain the exact folder layout mentioned above. Using the above mentioned code snippet, the archive contains everything except the parent folder which is a deal breaker for the external service:
- child folder 1
- child folder 2
- file1
- file2
The description of buildFromDirectory does mention the following so it not containing the parent folder in the archive is understandable:
Construct a tar/zip archive from the files within a directory.
I have also tried using buildFromIterator but the end result with it also the same, i.e the parent folder isn't included in the archive. I was able to get the desired result using addFile but this is painfully slow.
Having done a bit more research I found the following library : https://github.com/alchemy-fr/Zippy . But this requires composer support which isn't available on the server. I'd appreciate if someone could guide me in achieving the end result. I am also open to using some other methods or library so long as its pure PHP implementation and doesn't require any external dependencies. Not sure if it helps but the server where the code will get executed has PHP 5.6
Use the parent of "parent-folder" as the base for Phar::buildFromDirectory() and use its second parameter to limit the results only to "parent-folder", e.g.:
$parent = dirname("parent-folder");
$pd->buildFromDirectory($parent, '#^'.preg_quote("$parent/parent-folder/", "#").'#');
$pd->compress(Phar::GZ);
I ended up having to do this, and as this question is the first result on google for the problem here's the optimal way to do this, without using a regexp (which does not scale well if you want to extract one directory from a directory that contains many others).
function buildFiles($folder, $dir, $retarr = []) {
$i = new DirectoryIterator("$folder/$dir");
foreach ($i as $d) {
if ($d->isDot()) {
continue;
}
if ($d->isDir()) {
$newdir = "$dir/" . basename($d->getPathname());
$retarr = buildFiles($folder, $newdir, $retarr);
} else {
$dest = "$dir/" . $d->getFilename();
$retarr[$dest] = $d->getPathname();
}
}
return $retarr;
}
$out = "/tmp/file.tar";
$sourcedir = "/data/folder";
$subfolder = "folder2";
$p = new PharData($out);
$filemap = buildFiles($sourcedir, $subfolder);
$iterator = new ArrayIterator($filemap);
$p->buildFromIterator($iterator);
$p->compress(\Phar::GZ);
unlink($out); // $out.gz has been created, remove the original .tar
This allows you to pick /data/folder/folder2 from /data/folder, even if /data/folder contains several million OTHER folders. It then creates a tar.gz with the contents all being prepended with the folder name.
I am given a lot of video files on my server folder, so adding all of them is impossible, I need to develop a php script that will read the contents of a folder and populate my database table with details such as filename, size, path, etc.
Furthermore I need to use that data for displaying the video list to users so everything must be accurate.
Please tell me how to?
I suggest you to use Iterators from SPL (Standart PHP Library) for an OOP aproach, for recursive iterations you should use DirectoryRecursiveIterator;
$directoryIterator = new RecursiveDirectoryIterator("/path/");
$recursiveIterator = new RecursiveIteratorIterator($directoryIterator);
foreach ($recursiveIterator as $filename => $fileInfo) {
$filesize = $fileInfo->getSize();
$path = $fileInfo->getPath();
//insertDataIntoMysql($filename, $filesize, $filepath);
}
See here to see how to loop through a directory and get the filenames and file sizes. (Copied and edited here for simplicity)
$folder = '/my/path/to/dir';
foreach(glob($folder) as $file){
$size = filesize($file);
echo "Name=$file, size=$size<br />";
}
Instead of using echo to display the results you will simply use mysqli or PDO functions to run an INSERT query to insert into your table. Since this is not input coming from a user it is not so imperative to use prepare and bind but it is good practice to do so (and more efficient as well).
Then when you display the video list you will once again use mysqli or PDO functions to run a SELECT query and then echo these values onto your page in appropriate HTML syntax.
I'm guessing, based on your question, that some of these concepts might be new to you. If you do not know how to program in PHP or use SQL or create HTML pages then you are going to need to spend some serious time going through tutorials and watching youtube videos and reading books.
I'm a newbie in SPL and recursiveIterator... So could you help me?
What I want to achieve :
I would like to find a file in a folders tree and i would like to obtain its path.
My folder tree could seems to be like this :
./ressources
./ressources/Images
./ressources/Images/Image01
./ressources/Images/Image02
./resources/Images/ImagesSub/Image03
./ressources/Docs
./ressources/Docs/Doc01
and so on...
I obtain the name of my File with sql query (warning : they never have an extension).
Now, i want to find the file's location by doing a recursive Iterator on './ressources' folder.
Then, when i've found the file, i would like to return the whole link './ressources/Folder/File'.
I've read Gordon's solution but it doesn't work, I tried only to echo something, but doesn't display anything.
Here is my code :
$doc_id = $bean->id;
$query = "SELECT a.document_revision_id FROM documents as a, document_revisions as b ";
$query .= "WHERE a.document_revision_id = b.id AND a.id = '" . $doc_id . "' LIMIT 1";
$results = $bean->db->query($query, true);
$row = $bean->db->fetchByAssoc($results);
$file_id = $row['document_revision_id'];
$ressources = './ressources/';
$iter = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($ressources, RecursiveDirectoryIterator::KEY_AS_FILENAME), RecursiveIteratorIterator::SELF_FIRST);
foreach ($iter as $entry) {
if ($entry->getFilename() === $file_id){
echo '<script> alert('.$entry->getFilepath().');</script>';
}
}
(i know doing an alert into a echo is bullsh*t, but whith sugar it is quite difficult to display something
Specifications
I'm trying to do this in a SugarCrm CE 6.5.2 logic_hook and it's running on archlinux. And my PHP version is 5.4.6
It is really urgent, so I would be reaaaally happy if you could help me!!
Thanks by advance!
EDIT FROM 12/10/09 2pm:
What is my sugar project and why i can't get the pathname from my database
I created a custom field in Documents module called folder_name_c. You fill it with the name of the folder (under ressources) where you want to upload your document.
I want to allow the user to move the file uploaded from its ancient folder to new one when i edit the document.
When editing a document, I did a after_retrieve hook to permit the logic_hook to work when editing (before, it was just done for edit view)
So, if i get the $bean->folder_name_c, it pick up the field's content. If i try sql, it will pick the folder_name_c only after i click "save".
So, i don't have any clue to get my old folder_name to create an
$old_link = '.ressources/'.$old_folder.'/'.$file_id;
I can only create the
$new_link = '.ressources/'.$bean->folder_name_c.'/'.$file_id;
So, after a long time, i figured out that i could browse my ressources folder and my sub folders to find my file named $file_id and then create the $old_link
FYI, by creating a new custom field under studio in sugar, i gained a lot of time.
I don't want to pass my life on adding a custom_code calling database or else. this is URGENT and recursive iterator seems to be simple and quick.
There is no method such as getFilepath for the (Recursive)DirectoryIterator, just use $entry itself, when used in a string context it's casted to such one (à la __toString):
$file_id = 'test';
$ressources = './ressources/';
// [...]
echo '<script>alert('.$entry.');</script>'; // is casted to a string which contains the full path
// results in alerting ./resources/SubFolder/test
I tested it with the same structure and without extension.
So, I've found out how to use recursive iterators for my problem!
Here is my code :
$ressources = './ressources/';
$directoryIter = new RecursiveDirectoryIterator($ressources);
$iter = new RecursiveIteratorIterator($directoryIter, RecursiveIteratorIterator::SELF_FIRST);
$old_path = '';
$new_path = $ressources.$bean->folder_name_c.'/'.$file_id;
chmod($new_path,0777);
foreach ($iter as $entry) {
if (!$directoryIter->isDot()) {
if ($entry->getFileName() == $file_id) {
$old_path = $entry->getPathName();
chmod($old_path, 0777);
copy($old_path,$new_path);
}
}
}
So i succeed to get my file's origin path! :)
But as always, there is a problem:
I want to cut and paste my file from $old_path to $new_path (as you can see in my code). The copy here works well, but i don't know where i have to unlink() the old_path.. if anyone knows ...
(and if i wrote the copy in the wrong line, just tell me please! :D )
I have been looking for a convenient way of making and maintaining translations of my Kohana-modules. I have played around with POEdit and have extracted all __()'s from my modules. Really like the way POedit works, and it's just to run a quick update to gather all new strings and save a new catalog later on. I could afterwards convert the po-files to PHP-arrays sort of...it seems a bit complicated with all steps.
I have seen this approach but I would rather not install tables and new modules for translations, I think this gets to complicated and "drupalish" ;-).
How do you managing localizations and translations on different languages in your Kohana-projects? Any hints would be much appreciated!
This is how I did it. First of all POEdit for Mac is very buggy and strange, unfortunately.
In POEdit, created a new catalog with correct path and __ as a keyword.
Run POEdit to extract all the strings.
After this I ran this simple PHP-script over the generated PO-file. The output from the script I pasted into the files in i18n-folder of the project.
$file = 'sv_SE.po';
$translations = array();
$po = file($file);
$current = null;
foreach ($po as $line) {
if (substr($line,0,5) == 'msgid') {
$current = trim(substr(trim(substr($line,5)),1,-1));
}
if (substr($line,0,6) == 'msgstr') {
$translations[$current] = trim(substr(trim(substr($line,6)),1,-1));
}
}
echo "<?php\n\n";
foreach ($translations as $msgid => $msgstr) {
echo '\'' . $msgid . '\' => \'' . $msgstr . "',\n";
}
echo "\n?>";
By using POEdit it's easy to maintain the project-localizations since it's syncing all the strings but just clicking "Update". I'll get a report of new and obsolete strings and can update the localizations in a few moments. Hope it helps someone.
Try this I18n_Plural module. I like how it handles plural forms, very simple and easy. There is a lot of examples in readme file (showing on a main module page).
OK, whats the best solution in php to search through a bunch of files contents for a certain string and replace it with something else.
Exactly like how notepad++ does it but obviously i dont need the interface to that.
foreach (glob("path/to/files/*.txt") as $filename)
{
$file = file_get_contents($filename);
file_put_contents($filename, preg_replace("/regexhere/","replacement",$file));
}
So I recently ran into an issue in which our web host converted from PHP 5.2 to 5.3 and in the process it broke our installation of Magento. I did some individual tweaks that were suggested, but found that there were still some broken areas. I realized that most of the problems were related to an issue with the "toString" function present in Magento and the now deprecated PHP split function. Seeing this, I decided that I would try to create some code that would find and replace all the various instances of the broken functions. I managed to succeed in creating the function, but unfortunately the shot-gun approach didn't work. I still had errors afterwards. That said, I feel like the code has a lot of potential and I wanted to post what I came up with.
Please use this with caution, though. I'd recommended zipping a copy of your files so that you can restore from a backup if you have any issues.
Also, you don't necessarily want to use this as is. I'm providing the code as an example. You'll probably want to change what is replaced.
The way the code works is that it can find and replace whatever is in the folder it is put in and in the sub folders. I have it tweaked so that it will only look for files with the extension PHP, but you could change that as needed. As it searches, it will list what files it changes. To use this code save it as "ChangePHPText.php" and upload that file to wherever you need the changes to happen. You can then run it by loading the page associated with that name. For example, mywebsite.com\ChangePHPText.php.
<?php
## Function toString to invoke and split to explode
function FixPHPText( $dir = "./" ){
$d = new RecursiveDirectoryIterator( $dir );
foreach( new RecursiveIteratorIterator( $d, 1 ) as $path ){
if( is_file( $path ) && substr($path, -3)=='php' && substr($path, -17) != 'ChangePHPText.php'){
$orig_file = file_get_contents($path);
$new_file = str_replace("toString(", "invoke(",$orig_file);
$new_file = str_replace(" split(", " preg_split(",$new_file);
$new_file = str_replace("(split(", "(preg_split(",$new_file);
if($orig_file != $new_file){
file_put_contents($path, $new_file);
echo "$path updated<br/>";
}
}
}
}
echo "----------------------- PHP Text Fix START -------------------------<br/>";
$start = (float) array_sum(explode(' ',microtime()));
echo "<br/>*************** Updating PHP Files ***************<br/>";
echo "Changing all PHP containing toString to invoke and split to explode<br/>";
FixPHPText( "." );
$end = (float) array_sum(explode(' ',microtime()));
echo "<br/>------------------- PHP Text Fix COMPLETED in:". sprintf("%.4f", ($end-$start))." seconds ------------------<br/>";
?>