Listing directory contents with unusual characters file names - php

The following code is for listing every file and folder of a directory in alphabetical order, and it works perfectly ... almost.
<?php
$files = array();
$dir = opendir('.');
while(false != ($file = readdir($dir))) {
if(($file != ".")and ($file != "..") and ($file != "index.php")) {
$files[] = $file;
}
}
natsort($files);
foreach($files as $file) {
echo("<li><a href='$file'>$file</a>");
}
?>
The situation is that my files and folders have some strange characters in their names, like é, ï, être.htm, écouter.txt, etc. When I click on the links listed by the code above the links containing non Ascii characters lead to error 404 and the target is not opened, whereas the links with no strange characteres are fully operational.
Can you please tell me how to solve this?

Try this
echo("<li><a href='".url_encode($file)."'>$file</a>");
You said that spaces were a problem but url_encode would've made the space a %20 so I'm not sure why you have an issue

Solution:
`echo("<li><a href='".rawurlencode($file)."'>$file</a>");`
RFC 3986 - space replaced with %20

Found the solution myself and thanks to «Forbs».
When extracting or getting the URL path of a file ($file in the code above) I followed two steps: The use of urlencode($file) and str_replace("+", "%20", $url). The reason for this is that urlencode is perfect for changing unusual characters for the proper URL encoding, but this function also replaces the spaces in the URL path for a plus sign (+). Therefore, you need to use str_replace("+", "%20", $url) to replace every plus sign for the right URL encoding: %20.
So, here is the final PHP programming for listing the contents of a folder with unusual characters in file names (e.g. être.txt, écouter.php, canción.mp3).
DIRECTORY LISTING
<?php
$files = array();
$dir = opendir('.');
while(false != ($file = readdir($dir))) {
if(($file != ".") and ($file != "..") and ($file != "index.php"))
{
$files[] = $file;
}
}
natsort($files);
foreach($files as $file)
{
$url_1 = urlencode($file);
$url_2 = str_replace("+", "%20", $url_1);
echo "<li><a href='".$url_2."'>".$file."</a></li>";
}
?>
That's it. I hope it's of some use.

Related

How to echo out the contents of every text file that in a directory?

I have created a directory with some files in there:
index.php
one.txt
two.txt
three.txt
four.txt
In the index.php page, I am currently using this code to echo out all of the files within the directory:
<?php
$blacklist = array("index.php");
if ($handle = opendir('.')) {
while (false !== ($entry = readdir($handle))) {
if ($entry != "." && $entry != ".." && !in_array($entry, $blacklist)) {
echo "$entry\n";
}
}
closedir($handle);
}
?>
Now, if anyone views the index.php page, this is what they'll see:
one.txt two.txt three.txt four.txt
As you can see from the PHP code, index.php is blacklisted so it is not echoed out.
However, I would like to go a step further than this and echo out the contents of each text file rather than the filenames. With the new PHP code (that I need help with creating), whenever someone visits the index.php page, this is what they'll now see:
(Please ignore what is in the asterisks, they are not a part of the code, they just indicate what each text file contains)
Hello ** this is what the file **one.txt** contains **
ok ** this is what the file **two.txt** contains **
goodbye ** this is what the file **three.txt** contains **
text ** this is what the file **four.txt** contains **
Overall:
I would like to echo out the contents of every file in the directory (they are all text files) aside from index.php.
You could use file_get_contents to put the file into a string.
<?php
$blacklist = array("index.php");
if ($handle = opendir('.')) {
while (false !== ($entry = readdir($handle))) {
if ($entry != "." && $entry != ".." && !in_array($entry, $blacklist)) {
echo "$entry " . file_get_contents($entry) . "\n";
}
}
closedir($handle);
}
?>
Furthermore, you could use PHP's glob function to filter only the .txt files out, that way you do not have to blacklist files if you're going to be adding more files to that directory that need ignored.
Here is how it would be done using the glob function.
<?php
foreach (glob("*.txt") as $filename) {
echo "$filename " . file_get_contents($filename) . "\n";
}
?>
This would print the contents of the files. You can do some workaround if the path is not the current path and writing some kind of boundary between the files contents.
<?php
$blacklist = array("index.php");
if ($handle = opendir('.')) {
while (false !== ($entry = readdir($handle))) {
if ($entry != "." && $entry != ".." && !in_array($entry, $blacklist)) {
echo file_get_contents($entry) . "\n";
}
}
closedir($handle);
}
?>
I hope this helps you.
Never reinvent the wheel. Use composer.
Require symfony/finder
use Symfony\Component\Finder\Finder;
class Foo
{
public function getTextFileContents($dir)
{
$finder = (new Finder())->files()->name('*.txt');
foreach ($finder->in($dir) as $file) {
$contents = $file->getContents();
// do something while file contents...
}
}
}
I would give a chance to some SPL filesystem iterators to accomplish such this task:
$dir = '/home/mydirectory';
$rdi = new \RecursiveDirectoryIterator($dir, \FilesystemIterator::SKIP_DOTS);
$rdi = new \RegexIterator($rdi, '/\.txt$/i');
$iterator = new \RecursiveIteratorIterator($rdi, \RecursiveIteratorIterator::CHILD_FIRST);
foreach ($iterator as $file) {
echo 'Contents of the '.$file->getPathname().' is: ';
echo file_get_contents($file->getPathname());
}
This will recursively find & iterate all .txt files in given directory, including sub-directories.
Since each $file in iteration is a FilesystemIterator instance, you can use all related methods for additional controls like $file->isLink() (true for symbolic links), $file->isReadable() (false for unreadable files) etc..
If you don't want lookup sub-folders, just change the RecursiveDirectoryIterator in the second line from:
$rdi = new \RecursiveDirectoryIterator($dir, \FilesystemIterator::SKIP_DOTS);
to:
$rdi = new \DirectoryIterator($dir, \FilesystemIterator::SKIP_DOTS);
Hope it helps.
As #brock-b said, you could use glob to get the full list of files and file_get_contents to grab the contents:
$blacklist = array('index.php');
$files = glob('*.txt'); # could be *.* if needed
foreach ($files as $file) {
if (!in_array(basename($file), $blacklist)) {
echo file_get_contents($file);
}
}
Note: the blacklist wont be hit since you're seeking for *.txt files. Only useful when doing an *.* or *.php file search

php how to have links with spaces automatically add %20 [duplicate]

This question already has answers here:
Using PHP Replace SPACES in URLS with %20
(6 answers)
Closed 8 years ago.
i have this code that is listing all my mp3 links in the directory, but the audio player won't play any files that have spaces in the file names, if i remove the spaces, it works but i was wondering if i can some how have the script add %20 when there is a space in the file name and that way the audio player i am using can pickup on it
Thanks!
heres my code
<ul id="playlist">
<?php
$dirFiles = array();
// opens images folder
if ($handle = opendir('.')) {
while (false !== ($file = readdir($handle))) {
// strips files extensions
$crap = array(".jpg", ".jpeg", ".JPG", ".JPEG", ".png", ".PNG", ".gif", ".GIF", ".bmp", ".BMP", "_", "-", "error_log", ".php");
$newstring = str_replace($crap, " ", $file );
//asort($file, SORT_NUMERIC); - doesnt work :(
// hides folders, writes out ul of images and thumbnails from two folders
if ($file != "." && $file != ".." && $file != "index.php" && $file != ".DS_Store" && $file != "download.php" && $file != "error_log" && $file != "Thumbnails") {
$dirFiles[] = $file;
}
}
closedir($handle);
}
sort($dirFiles);
foreach($dirFiles as $file)
{
//echo "<li><img style=\"padding-right: 10px;vertical-align: middle;height: 60px;\" src=\"http://www.ggcc.tv/LogoNE.png\" />";
echo '<li><a href="'.$file.'">'.$file.'<br></li>';
}
?>
</ul>
try rawurlencode or other Url Functions
echo '<li><a href="'.rawurlencode($file).'">'.$file.'<br></li>';
Use str_replace to replace spaces with %20.
$fileURL = str_replace(' ', '%20', $file);
echo '<li><a href="'.$fileURL.'">'.$file.'<br></li>';
Alternatively one may modify the foreach loop as follows:
foreach($dirFiles as $file)
{
$url = join("%20",explode(' ',$file ) );
echo '<li><a href="'.$url.'">'.$file.'<br></li>';
}
The first statement encodes only spaces and assigns the result for later use by the HREF attribute of the <a> tag. rawurlencode is another option to achieve a similar result, but it may also encode more than just space characters which at times is good and other times may cause undesirable effects, such as encoding a character that is part of a domain name. str_replace is probably the sleeker solution since it requires only one function call instead of of the two shown in this snippet.
The TIMTOWDI aspect of PHP is particularly evident with this question. You may also do the following:
<?php
$from = ' ';
$to = '+';
foreach($dirFiles as $file)
{
$url = strtr( $file, $from, $to);
echo '<li><a href="'.$url.'">'.$file.'<br></li>';
}
With this solution, the replacement character for the space is the simple '+' (PHP's way of encoding spaces) and it uses strtr() which some think is faster than str_replace(). Any '+' characters will revert to spaces after the the browser automatically decodes the url.
see simple example here

Find file in a directory using preg_match?

I need to find a file in a directory that matches a certain condition. For example, I know the file name starts with '123-', and ends with .txt, but I have no idea what is in between the two.
I've started the code to get the files in a directory and the preg_match, but am stuck. How can this be updated to find the file I need?
$id = 123;
// create a handler for the directory
$handler = opendir(DOCUMENTS_DIRECTORY);
// open directory and walk through the filenames
while ($file = readdir($handler)) {
// if file isn't this directory or its parent, add it to the results
if ($file !== "." && $file !== "..") {
preg_match("/^".preg_quote($id, '/')."\\-(.+)\\.txt$/" , $file, $name);
// $name = the file I want
}
}
// tidy up: close the handler
closedir($handler);
I wrote up a little script here for ya, Cofey. Try this out for size.
I changed the directory for my own test, so be sure to set it back to your constant.
Directory Contents:
123-banana.txt
123-extra-bananas.tpl.php
123-wow_this_is_cool.txt
no-bananas.yml
Code:
<pre>
<?php
$id = 123;
$handler = opendir(__DIR__ . '\test');
while ($file = readdir($handler))
{
if ($file !== "." && $file !== "..")
{
preg_match("/^({$id}-.*.txt)/i" , $file, $name);
echo isset($name[0]) ? $name[0] . "\n\n" : '';
}
}
closedir($handler);
?>
</pre>
Result:
123-banana.txt
123-wow_this_is_cool.txt
preg_match saves its results to $name as an array, so we need to access by it's key of 0. I do so after first checking to make sure we got a match with isset().
You must test if the match was successful.
Your code inside the loop should be this:
if ($file !== "." && $file !== "..") {
if (preg_match("/^".preg_quote($id, '/')."\\-(.+)\\.txt$/" , $file, $name)) {
// $name[0] is the file name you want.
echo $name[0];
}
}

Listing Directories: Opendir()

I'm working on a small script and I want to list the contents of a directory, make them into hyperlinks, and then edit those hyperlinks to look pretty (I.e. not show an ugly super long path name), then limit the number files echoed back to the browser. Also, I need the most recent files echoed back only.
I was thinking about using this:
<?php
$path = "/full/path/to/files";
if ($handle = opendir($path)) {
while (false !== ($file = readdir($handle)))
{
if ($file != "." && $file != "..")
{
$files .= ''.$file.'';
}
}
closedir($handle);
}
?>
or this:
<?php
$sub = ($_GET['dir']);
$path = 'enter/your/directory/here/';
$path = $path . "$sub";
$dh = opendir($path);
$i=1;
while (($file = readdir($dh)) !== false) {
if($file != "." && $file != "..") {
if (substr($file, -4, -3) =="."){
echo "$i. $file <br />";
}else{
echo "$i. <a href='?dir=$sub/$file'>$file</a><br />";
}
$i++;
}
}
closedir($dh);
?>
But I dont want to list the files like this:
C:/example/example2/Hello.pdf
I want to edit the variable. Is that possible? To make it say something as simple as "Hello."
I want to limit the amount of files listed as well. For example: only list the first 5 files, or last 5, etc. Is there a function or some kind of parameter for that?
I appreciate any help or push in the right direction. Thanks
I'm on my phone so providing a code example will be tough. Why not iterate through the directories, storing the file name in an array, with the absolute path as the value for that key?
EDIT: You can use basename to aid you in doing this.

PHP readdir( ) returns " . " and " .. " entries

I'm coding a simple web report system for my company. I wrote a script for index.php that gets a list of files in the "reports" directory and creates a link to that report automatically. It works fine, but my problem here is that readdir( ) keeps returning the . and .. directory pointers in addition to the directory's contents. Is there any way to prevent this OTHER THAN looping through the returned array and stripping them manually?
Here is the relevant code for the curious:
//Open the "reports" directory
$reportDir = opendir('reports');
//Loop through each file
while (false !== ($report = readdir($reportDir)))
{
//Convert the filename to a proper title format
$reportTitle = str_replace(array('_', '.php'), array(' ', ''), $report);
$reportTitle = strtolower($reportTitle);
$reportTitle = ucwords($reportTitle);
//Output link
echo "$reportTitle<br />";
}
//Close the directory
closedir($reportDir);
In your above code, you could append as a first line in the while loop:
if ($report == '.' or $report == '..') continue;
array_diff(scandir($reportDir), array('.', '..'))
or even better:
foreach(glob($dir.'*.php') as $file) {
# do your thing
}
No, those files belong to a directory and readdir should thus return them. I’d consider every other behaviour to be broken.
Anyway, just skip them:
while (false !== ($report = readdir($reportDir)))
{
if (($report == ".") || ($report == ".."))
{
continue;
}
...
}
I would not know another way, as "." and ".." are proper directories as well. As you're looping anyway to form the proper report URL, you might just put in a little if that ignores . and .. for further processing.
EDIT
Paul Lammertsma was a bit faster than me. That's the solution you want ;-)
I wanted to check for the "." and the ".." directories as well as any files that might not be valid based on what I was storing in the directory so I used:
while (false !== ($report = readdir($reportDir)))
{
if (strlen($report) < 8) continue;
// do processing
}

Categories