Let's say I have a folder (folder_1) with the following structure:
/folder_1
/dir_1
- file_1_1.txt
- file_1_2.txt
/dir_2
- file_2_1.txt
/dir_2_1
- file_2_1_1.txt
- file_1.txt
Now, let's say I have another folder (folder_2) with the following structure:
/folder_2
/dir_1
- file_1_1.txt
- default.txt
/dir_2
- file_2_1.txt
- default.txt
- default.txt
I need to map every file in folder_1 to a file in folder_2 such that:
/folder_1/dir_1/file_1_1.txt maps to /folder_2/dir_1/file_1_1.txt.
/folder_1/dir_1/file_1_1.txt maps to /folder_2/dir_1/default.txt
/folder_1/dir_2/file_2_1.txt maps to /folder_2/dir_2/file_2_1.txt
/folder_1/dir_2/dir_2_1/file_2_1_1.txt maps to /folder_2/dir_2/default.txt
/folder_1/file_1.txt maps to /folder_2/default.txt
I am not the best communicator, so hopefully, the above pattern makes sense to you guys. The question is language agnostic really, but an answer in PHP and/or Javascript would be really great.
So far, I was able to accomplish this in PHP using FileIterator, RecursiveDirectoryIterator, and a bunch of custom classes that extract and then map the path to the files one by one.
This makes me wonder if I am missing an easier way to do this simple mapping. Maybe using regex named groups or something?
**Edit: **
Is it possible that for each file (file path) in folder_1, we use a regex pattern to find (reduce) the best match out of a map of all file paths in folder_2?
Further edit:
This is for mapping data files in folder_1 to template files in folder_2. If for a file in folder_1, an exact matching file path (including filename) in folder_2 is not found, we look for default.txt. If default.txt is not found, then we move up a directory and use that parent directory's default.txt. This way, we keep moving up directory levels till we find the first default.txt.
First, use your recursive directory scanner to scan all of the folder_2 directory tree. Build a hash table that contains the file names, without the folder_2 prefix. So your hash table would contain:
/dir_1
/dir_1/file_1_1.txt
/dir_1/default.txt
/dir_2/file_2_1.txt
/dir_2/default.txt
/default.txt
Now, start scanning folder_1. When you get a file, strip folder_1 from the front, and look for the resulting string in the hash table. If it's there, then you have a match.
If the file is not there, replace the last segment with "default.txt", and try again. So, when you begin scanning folder_1, you get:
/folder_1/dir_1/file_1_1.txt
You look up dir_1/file_1_1.txt in the hash table and find it. You have a match.
Next, you get /folder_1/dir_1/file_1_2.txt. You look up /dir_1/file_1_2.txt in the hash table and don't find it. So you replace file_1_2.txt with default.txt, giving you /dir_1/default.txt. You look that up in the hash table, find it, and you have a match.
Now, if /dir_1/default.txt did not exist, then you would again adjust the file name to remove the last directory. That is, you'd remove /dir_1, and you'd look up /default.txt in the hash table.
In pseudo code it looks like this:
for each file in folder_1
name = strip `/folder_1` from the name
if name in hash table then
match found
continue (next file)
end if
replace file name (everything after the last '/') with "default.txt"
do
if name in hash table then
match found
continue (next file)
end if
remove the last slash, and everything between it and the previous slash.
(so "/dir_1/default.txt" becomes "/default.txt")
while name.length > 0
// if you get here, no match was found
end for
Related
What I need Is to go thru a directory that contains subdirectories. In each second level directory has a third level directory that contains a file with same file name for every second level directory.
In each of those files made in PHP there Is a variable that contains like: appversion = 'YYYYMMDD'. I need to modify this date for each appearance To eg appversion = '20190301'.
How to do this In Shell or with PHP?
Edit: sorry for the malformed question, this is what defines better what I need to do really
I am afraid the question was a little malformed.
What I need to do is:
1. To find in all subdirectories a file called "productver.php".
2. In each "productver.php" file find a variable called 'appversion'.
3. Replace the value with a given value that i provide.
Example: I provide a date that is "20190324" and I want to change this to the value of all 'appversion' variables. E.g. 'appversion = 20180121' ==> 'appversion = 20190324'. For this reason, I am afraid simple replace is not enough as I only need to replace the part which is on the right side of the "=" character. And I cannot seek for a specific date, because the dates of this variable change. All I know is that I need to replace those dates, on the right side of the "=" sign of variable 'appversion'.
Is it possible to get translation from language file that contains (.)dot?
For example, The language directory looks like
/lang
/en
pagination.php
phone.history.php
/es
pagination.php
phone.history.php
phone.history.php file contains dot and want to get translation for the key 'name' from phone.history.php file.
Lang::get('phone.history.name')
It doesn't work.
Actually the Laravel key used for translations can only contain one dot . in order to work and the function of that dot is to separate the translation file path (relative to the language directory) from the translation array key. That's because the Translator class extends the Illuminate\Support\NamespacedItemResolver class, which parses the key using the following logic:
First it determines if there is a namespace present (denoted by ::) and extracts it.
It then goes on to split the key into a group (which is the relative filepath) and an item (which is the translation array key).
So in your case since there is no namespace, when you use this:
Lang::get('phone.history.name')
The result is the following:
The filename will be phone
The translation array key will be history (instead of name)
And since there's no phone.php in your language directory, it won't work.
So you have two options here:
Use another character in your filename so there's only one dot in the translator parameter, something like /lang/en/phone_history.php and then use Lang::get('phone_history.name').
Use a subdirectory if you want to group some translation files, something like /lang/en/phone/history.php and then use Lang::get('phone/history.name') (unfortunately, as I said above you can only use one dot as a separator, so you can't use the multiple level dot notation as you would for a configuration file Lang::get('phone.history.name')).
There is actually a 3rd option which is to use dotted key names. So inside /lang/en/phone.php you can set 'history.name' => 'John Doe' and then retrieve that using trans('phone.history.name').
I am using a PHP GET method to grab a file name that then is placed in a get_file_contents command. If it is possible, I would like to ignore letter case so that my URL's are cleaner.
For instance, example.com/file.php?n=File-Name will work but example.com/file.php?n=file-name will not work using the code below. I feel like this should be easy but I'm coming up dry. Any thoughts?
$file = $_GET['n'];
$file_content = file_get_contents($file);
Lowercase all your filenames and use:
file_get_contents(strtolower($file));
(I hope you're aware of some of the risks involved in using this.)
The Linux filesystem is case sensitive. If you want to do case insensitive matching against files that already exist on the user's machine, your only option is to obtain a directory listing and do case-insensitive comparison.
But you don't explain where the download URLs come from. If you already know the correct filenames and you want to generate prettier URLs, you can keep a list of the true pathnames and look them up when you receive a case-normalized one in a URL (you could even rename them completely, obfuscate, etc.)
Not sure if the title for this is correct but here's my problem:
I have a table that hold image's url like so:
img/folder/imagename.jpg
Now I've created a thumbnail for each image in each folder, so if I want to display them I do a loop in my table and return all the url's but I need to add the word "thumbs" after "folder/" and before the "imagename.jpg"...Now because obviously the "folder" and "imagename" names differ in length then I can't do a count..the only thing I can figure is to look up that last "/" character and insert there and add on the "imagename.jpg" after it so end result would look like:
img/folder/thumbs/imagename.jpg
Just replace the path with a "deeper" path:
$path = str_replace('img/folder/', 'img/folder/thumbs/', $path);
There are lots of other ways to do this, but IMHO this one is perfectly clear on what it does. Theoretically it won't work universally (if your path contains multiple occurreces of img/folder/ for some reason), but let's just not go there.
you can also
$pathparts = explode("/",$path);
and then use $pathparts array to construct your path again. You would use it in cases you want to have more control over manipulating paths, but in heavy loads it's not very efficient.
echo $pathparts[0]."/".$pathparts[1]."/thumbs/".$pathparts[2];
//adition
And why not to update your database and script only save imagename.jpg
and then in the beginning of calling script define
define("IMGPATH", "img/folder/");
define("THUMBPATH", "img/folder/thumbs/");
and then call it
<?= IMGPATH."imagename.jpg" ?>
<?= THUMBPATH."imagename.jpg" ?>
I am trying to make a news feed type thing in php.
I have a text file - news.txt and a php file index.php.
I have done the surrounding code and opening/closing the text file. Now I am stuck how to insert the new news item $newsnew to the top of the news.txt file and how to delete the old bottom news file in the news.txt file.
Is there any way to do this without deleting the whole file and writing it all again?
EDIT: Each news item is just a small string, say 500 characters, a single line.
Use a database.
If you really must use text files, use a different file for every news-item and name them sequentially like:
news001.txt
news002.txt
etc.
Then you can just add and delete files, read the directory and display what´s there.
Use the file() function to import the items in news.txt as an array, and use array_unshift() to add the new first item, and array_pop() to remove the last item. Join the array back into a single string and write it to news.txt:
$items = file('news.txt');
array_unshift($items, 'New item 1');
array_pop($items);
$newstext = implode(PHP_EOL, $items);
// write $newstext to the external file
If this is a XML file you could read it, parse it and delete the last child in the DOM. But if you have all your data in a DB it could be much easier to rewrite the file every time.
EDIT: after your edit: yes, you can do it like this:
write your new line to a new file
read the old file line by line and write it to the new one
skip the last line (detected by counting or EOF)
delete the old file and rename the new
No, there is not. But you might consider storing the messages in revers order. That way you only need to append to news.txt when new news arrive.
You are not going to be able to prepend to the beginning of the file without writing the whole thing out again. You could append to the end of it with the "a" mode flag to fopen(), but still to delete the oldest item you'll need to write out the entire file again.
Really, a database is solution here instead of a single text file.
There are many ways you can do it using the flat text file, but I'm not really sure it it's worth it. You can use some lightweight structured file or embedded database. For example SQLite, which would store it in normal file, no additional setup needed.