I have a script that gets a string from a config file and based on that string grabs the file names of a folder.
I now only need the iso files. Not sure if the best way is to check for the .iso string or is there another method?
<?php
// Grab the contents of the "current.conf" file, removing any linebreaks.
$dirPath = trim(file_get_contents('current.conf')).'/';
$fileList = scandir($dirPath);
if(is_array($fileList)) {
foreach($fileList as $file) {
//could replace the below if statement to only proceed if the .iso string is present. But I am worried there could be issues with this.
if ($file != "." and $file != ".." and $file != "index.php")
{
echo "<br/><a href='". $dirPath.$file."'>" .$file."</a>\n";
}
}
}
else echo $dirPath.' cound not be scanned.';
?>
If you only need the files with an extension of .iso, then why not use:
glob($dirPath.'/*.iso');
rather than scandir()
try this:
if(is_array($fileList)) {
foreach($fileList as $file) {
$fileSplode = explode('.',$file); //split by '.'
//this means that u now have an array with the 1st element being the
//filename and the 2nd being the extension
echo (isset($fileSplode[1]) && $fileSplode[1]=='iso')?
"<br/><a href='". $dirPath.$file."'>" .$file."</a>\n":'');
}
}
If you want it in an OOP style you could use:
<?php
foreach (new DirectoryIterator($dirPath) as $fileInfo) {
if($fileInfo->getExtension() == 'iso') {
// do something with it
}
}
?>
Related
I am very inexperienced with PHP. I have a folder on a website which will receive files named with a numeric date structure. I need href links to be created for the files which are dropped into this folder. I need the link text to be formatted by with a textual month and numeric day. For example:
File name "01-02-22 BULLETIN.pdf" becomes
<href="bulletins/2022/$file">January 2</a>.
I have been messing with the code below from this post PHP to create Links for files in a folder, but I can't seem to figure it out. The links are appearing but any date formatting I attempt returns "error Call to a member function format()."
Thanks for your help!
<?php
$dir = "bulletins/2022/";
// Open a directory, and read its contents
if (is_dir($dir)){
if ($dh = opendir($dir)){
while (($file = readdir($dh)) !== false){
echo "<a href=bulletins/2022/$file>$file</a><br>";
}
closedir($dh);
}
}
?>
The html mark up is missing quotes
Here an example:
$some_path = "bulletins/2022";
$readdir=opendir($some_path);
while ($file = readdir($readdir))
{
if($file != '..' && $file !='.' && $file !='' && $file != ".htaccess")
{
echo "$file<br>"; // yours is missing the quotes which should always be escaped in php with a backslash
}
}
closedir($readdir);
You could also concider using php time(); as the filename which will give you a unix timestamp which can then be sorted and converted into a date and time.
This example will sort the files in a natural order
$some_path = "demo_track_previews";
$readdir=opendir($some_path);
while ($file = readdir($readdir))
{
if($file != '..' && $file !='.' && $file !='' && $file != ".htaccess")
{
if(!empty(file))
{
$all_files[] = $file; //put all files in array ready to sort
}
}
}
closedir($readdir);
if(!empty($all_files))
{
sort($all_files,SORT_NATURAL); //You can also try rsort($all_files,SORT_NATURAL);
foreach ($all_files as $key => $each_file)
{
echo "".$each_file."<br>";
}
}
EDIT: after comment
if you need just the date from the filename "01-02-22 BULLETIN.pdf"
then try this
foreach ($all_files as $key => $each_file)
{
$file_name_parts = explode(" ", $each_file); // seperate the filename where there is a space - $file_name_parts[0] will be 01-02-22
echo "".$file_name_parts[0]."<br>";
}
I would like to list all .jpg files from folders and subfolders.
I have that simple code:
<?php
// directory
$directory = "img/*/";
// file type
$images = glob("" . $directory . "*.jpg");
foreach ($images as $image) {
echo $image."<br>";
}
?>
But that lists .jpg files from img folder and one down.
How to scan all subfolders?
Php coming with the DirectoryIterator which can be very useful in that case.
Please note that this simple function can be easly improved by adding the whole path to a file instead the only file name, and maybe use something else instead of the reference.
/*
* Find all file of the given type.
* #dir : A directory from which to start the search
* #ext : The extension. XXX : Dont call it with "." separator
* #store : A REFERENCE to an array on which store the element found.
* */
function allFileOfType($dir, $ext, &$store) {
foreach(new DirectoryIterator($dir) as $subItem) {
if ($subItem->isFile() && $subItem->getExtension() == $ext)
array_push($store, $subItem->getFileName());
elseif(!$subItem->isDot() && $subItem->isDir())
allFileOfType($subItem->getPathName(), $ext, $store);
}
}
$jpgStore = array();
allFileOfType(__DIR__, "jpg", $jpgStore);
print_r($jpgStore);
As a directotry can contain subdirectories, and in their turn contains subdirectories, so we should use a recursive function. glob() is here not sufficient. This might work for you:
<?php
function getDir4JpgR($directory) {
if ($handle = opendir($directory)) {
while (false !== ($entry = readdir($handle))) {
if($entry != "." && $entry != "..") {
$str1 = "$directory/$entry";
if(preg_match("/\.jpg$/i", $entry)) {
echo $str1 . "<br />\n";
} else {
if(is_dir($str1)) {
getDir4JpgR($str1);
}
}
}
}
closedir($handle);
}
}
//
// call the recursive function in the main block:
//
// directory
$directory = "img";
getDir4JpgR($directory);
?>
I put this into a file named listjpgr.php. And in my Chrome Browser, it gives this capture:
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
I'm creating a intranet for my workplace and have used a bit of php I found online to scan the contents of the folder it's in and display them as links. It does this fine, but when it's inside an empty folder I would like it to display a message such as "There are no records matching those criteria.".
Is there a way to add something to the php to specify if there are no folders listed print this?
I have next to no knowledge of php, but html and css are no problem.
Here's the php I'm using in the page:
<?php
$dir=opendir(".");
$files=array();
while (($file=readdir($dir)) !== false)
{
if ($file != "." and $file != ".." and $file != "A.php")
{
array_push($files, $file);
}
}
closedir($dir);
sort($files);
foreach ($files as $file)
print "<div class='fileicon'>
<a href='$file'>
<img src='../../../images/TR-Icon.png'>
<p class='filetext'>$file</p>
</a>
</div>";
?>
If you need anymore code such as the full page html or css just let me know.
Thanks in advance for any help.
EDIT:
After trying Josh's solution it pretty much nailed it, but I'm now getting "No files found" printing 3 times. Here's the code I'm using now:
<?php
$dir=opendir(".");
$files=array();
while (($file=readdir($dir)) !== false)
{
if( count($files) == 0 )
{
echo '<p>No files found</p>';
}
else
{
if ($file != "." and $file != ".." and $file != "A.php")
{
array_push($files, $file);
}
}
}
closedir($dir);
sort($files);
foreach ($files as $file)
print " <div class='fileicon'>
<a href='$file'>
<img src='../../../images/TR-Icon.png'>
<p class='filetext'>$file</p>
</a>
</div>";
?>
Just do an:
if( count($files) == 0 )
{
echo '<p>No files found</p>';
}
else
{
// you have files
}
You can use the count function to check if there are any files in your files array like this:
if(count($files) > 0) // check if there are any files in the files array
foreach ($files as $file) // print the files if condition is true
print " <a href='$file'>$file</a> <br />";
else
echo "ERROR!";
EDIT:
You can also use the scandir function. However, this function will return two extra entries for the current directory and directory up one level. You need to remove these entries from the files array. Your code will look like this:
<?php
$dir = "."; // the directory you want to check
$exclude = array(".", ".."); // you don't want these entries in your files array
$files = scandir($dir);
$files = array_diff($files, $exclude); // delete the entries in exclude array from your files array
if(!empty($files)) // check if the files array is not empty
{
foreach ($files as $file) // print every file in the files array
print " <div class='fileicon'>
<a href='$file'>
<img src='../../../images/TR-Icon.png'>
<p class='filetext'>$file</p>
</a>
</div>";
}
else
{
echo "There are no files in directory"; // print error message if there are noe files
}
?>
Try This:
<?php
$dir=opendir(".");
$files=array();
while (($file=readdir($dir)) !== false)
{
if ($file != "." and $file != ".." and $file != "A.php")
{
array_push($files, $file);
}
}
closedir($dir);
if(count($files) == 0){
die("There are no records matching those criteria.");
}else{
sort($files);
foreach ($files as $file)
print " <div class='fileicon'>
<a href='$file'>
<img src='../../../images/TR-Icon.png'>
<p class='filetext'>$file</p>
</a>
</div>";
}
?>
You can use a simple conditional using count on your file array.
// ...
closedir($dir);
if (count($files) > 0) {
// sort files and iterate through file array, printing html
} else {
echo "There are no records matching those criteria.";
}
// ...
I think you could let it print something else if($files.length == 0) and only print it normally if($files.length > 0) or something.
I have no knowledge of php, but I know java, html, css, and javascript.
I'm sure php has things like array.length (or something else to get the length of an array) in it
I hope this was helpful.
EDIT: I've seen others already answered thigs that are like 10x better than mine.
Also, php seems pretty cool, I might learn it
when moving one file from one location to another i use
rename('path/filename', 'newpath/filename');
how do you move all files in a folder to another folder? tried this one without result:
rename('path/*', 'newpath/*');
A slightly verbose solution:
// Get array of all source files
$files = scandir("source");
// Identify directories
$source = "source/";
$destination = "destination/";
// Cycle through all source files
foreach ($files as $file) {
if (in_array($file, array(".",".."))) continue;
// If we copied this successfully, mark it for deletion
if (copy($source.$file, $destination.$file)) {
$delete[] = $source.$file;
}
}
// Delete all successfully-copied files
foreach ($delete as $file) {
unlink($file);
}
Please try this solution, it's tested successfully ::
<?php
$files = scandir("f1");
$oldfolder = "f1/";
$newfolder = "f2/";
foreach($files as $fname) {
if($fname != '.' && $fname != '..') {
rename($oldfolder.$fname, $newfolder.$fname);
}
}
?>
An alternate using rename() and with some error checking:
$srcDir = 'dir1';
$destDir = 'dir2';
if (file_exists($destDir)) {
if (is_dir($destDir)) {
if (is_writable($destDir)) {
if ($handle = opendir($srcDir)) {
while (false !== ($file = readdir($handle))) {
if (is_file($srcDir . '/' . $file)) {
rename($srcDir . '/' . $file, $destDir . '/' . $file);
}
}
closedir($handle);
} else {
echo "$srcDir could not be opened.\n";
}
} else {
echo "$destDir is not writable!\n";
}
} else {
echo "$destDir is not a directory!\n";
}
} else {
echo "$destDir does not exist\n";
}
tried this one?:
<?php
$oldfolderpath = "old/folder";
$newfolderpath = "new/folder";
rename($oldfolderpath,$newfolderpath);
?>
So I tried to use the rename() function as described and I kept getting the error back that there was no such file or directory. I placed the code within an if else statement in order to ensure that I really did have the directories created. It looked like this:
$tempDir = '/home/site/images/tmp/';
$permanentDir = '/home/site/images/' . $claimid; // this was stored above
mkdir($permanentDir,0775);
if(is_dir($permanentDir)){
echo $permanentDir . ' is a directory';
if(is_dir($tempDir)){
echo $tempDir . ' is a directory';
}else{
echo $tempDir . ' is not a directory';
}
}else{
echo $permanentDir . ' is not a directory';
}
rename($tempDir . "*", $permanentDir);
So when I ran the code again, it spit out that both paths were directories. I was stumped. I talked with a coworker and he suggested, "Why not just rename the temp directory to the new directory, since you want to move all the files anyway?"
Turns out, this is what I ended up doing. I gave up trying to use the wildcard with the rename() function and instead just use the rename() to rename the temp directory to the permanent one.
so it looks like this.
$tempDir = '/home/site/images/tmp/';
$permanentDir = '/home/site/images/' . $claimid; // this was stored above
mkdir($permanentDir,0775);
rename($tempDir, $permanentDir);
This worked beautifully for my purposes since I don't need the old tmp directory to remain there after the files have been uploaded and "moved".
Hope this helps. If anyone knows why the wildcard doesn't work in the rename() function and why I was getting the error stating above, please, let me know.
Move or copy the way I use it
function copyfiles($source_folder, $target_folder, $move=false) {
$source_folder=trim($source_folder, '/').'/';
$target_folder=trim($target_folder, '/').'/';
$files = scandir($source_folder);
foreach($files as $file) {
if($file != '.' && $file != '..') {
if ($move) {
rename($source_folder.$file, $target_folder.$file);
} else {
copy($source_folder.$file, $target_folder.$file);
}
}
}
}
function movefiles($source_folder, $target_folder) {
copyfiles($source_folder, $target_folder, $move=true);
}
try this:
rename('path/*', 'newpath/');
I do not see a point in having an asterisk in the destination
If the target directory doesn't exist, you'll need to create it first:
mkdir('newpath');
rename('path/*', 'newpath/');
As a side note; when you copy files to another folder, their last changed time becomes current timestamp. So you should touch() the new files.
... (some codes for directory looping) ...
if (copy($source.$file, $destination.$file)) {
$delete[] = $source.$file;
$filetimestamp = filemtime($source.$file);
touch($destination.$file,$filetimestamp);
}
... (some codes) ...
Not sure if this helps anyone or not, but thought I'd post anyway. Had a challenge where I has heaps of movies I'd purchased and downloaded through various online stores all stored in one folder, but all in their own subfolders and all with different naming conventions. I wanted to move all of them into the parent folder and rename them all to look pretty. all of the subfolders I'd managed to rename with a bulk renaming tool and conditional name formatting. the subfolders had other files in them i didn't want. so i wrote the following php script to, 1. rename/move all files with extension mp4 to their parent directory while giving them the same name as their containing folder, 2. delete contents of subfolders and look for directories inside them to empty and then rmdir, 3. rmdir the subfolders.
$handle = opendir("D:/Movies/");
while ($file = readdir($handle)) {
if ($file != "." && $file != ".." && is_dir($file)) {
$newhandle = opendir("D:/Movies/".$file);
while($newfile = readdir($newhandle)) {
if ($newfile != "." && $newfile != ".." && is_file("D:/Movies/".$file."/".$newfile)) {
$parts = explode(".",$newfile);
if (end($parts) == "mp4") {
if (!file_exists("D:/Movies/".$file.".mp4")) {
rename("D:/Movies/".$file."/".$newfile,"D:/Movies/".$file.".mp4");
}
else {
unlink("D:/Movies/".$file."/".$newfile);
}
}
else { unlink("D:/Movies/".$file."/".$newfile); }
}
else if ($newfile != "." && $newfile != ".." && is_dir("D:/Movies/".$file."/".$newfile)) {
$dirhandle = opendir("D:/Movies/".$file."/".$newfile);
while ($dirfile = readdir($dirhandle)){
if ($dirfile != "." && $dirfile != ".."){
unlink("D:/Movies/".$file."/".$newfile."/".$dirfile);
}
}
rmdir("D:/Movies/".$file."/".$newfile);
}
}
unlink("D:/Movies/".$file);
}
}
i move all my .json files from root folder to json folder with this
foreach (glob("*.json") as $filename) {
rename($filename,"json/".$filename);
}
pd: someone 2020?