I'm using scandir and a foreach loop to display a list of files in a directory to the user. My code is below:
$dir = scandir('/user1/caravans/public_html/wordpress/wp-content/uploads/wpallimport/files');
foreach($dir as $directory)
{
echo "<br/><input type='checkbox' name=\"File[]\" value='$directory'/>$directory<br>";
}
The problem is the script also echos a "." and a ".." (without the speech marks), is there an elegant way to remove these? Short or a regular expression. Thanks
Just continue if the directory is . or .. I recommend to take a look at the control structures here
$dir = scandir('/user1/caravans/public_html/wordpress/wp-content/uploads/wpallimport/files');
foreach($dir as $directory) {
if( $directory == '.' || $directory == '..' ) {
// directory is . or ..
// continue will directly move on with the next value in $directory
continue;
}
echo "<br/><input type='checkbox' name=\"File[]\" value='$directory'/>$directory<br>";
}
Instead of this:
if( $directory == '.' || $directory == '..' ) {
// directory is . or ..
// continue will directly move on with the next value in $directory
continue;
}
you can use a short version of it:
if( $directory == '.' || $directory == '..' ) continue;
You can eliminate these directories with array_diff:
$dir = scandir($path);
$dir = array_diff($dir, array('.', '..'));
foreach($dir as $entry) {
// ...
}
Another solution, in addition to swidmann's answer, is to simply remove '.' and '..' before iterating over them.
Adapted from http://php.net/manual/en/function.scandir.php#107215
$path = '/user1/caravans/public_html/wordpress/wp-content/uploads/wpallimport/files';
$exclude = ['.', '..'];
$dir = array_diff(scandir($path), $exclude);
foreach ($dir as $directory) {
// ...
}
That way you can also easily add other directories and files to the excluded list should the need arise in the future.
Related
I m trying to rename files to lowercase within a directory, however the problem I'm having is being able to scan the sub-directories for the files.
So in this case $app_dir is the main directory and the files I need to change exist within multiple sub-folders.
Heres my code so far:
$files = scandir($app_dir);
foreach($files as $key=>$name){
$oldName = $name;
$newName = strtolower($name);
rename("$app_dir/$oldName","$app_dir/$newName");
}
Thanks for your help.
If you are trying to lowercase all file names you can try this:
Using this filesystem:
Josh#laptop:~$ find josh
josh
josh/A
josh/B
josh/f1
josh/f2
josh/is
josh/is/awesome
josh/is/awesome/e
josh/is/awesome/t
Code:
<?php
$app_dir = 'josh';
$dir = new RecursiveDirectoryIterator($app_dir, FilesystemIterator::SKIP_DOTS);
$iter = new RecursiveIteratorIterator($dir);
foreach ($iter as $file) {
if ($file != strtolower($file)) {
rename($file, strtolower($file));
}
}
Results:
Josh#laptop:~$ find josh
josh
josh/a
josh/b
josh/f1
josh/f2
josh/is
josh/is/awesome
josh/is/awesome/e
josh/is/awesome/t
This code does not take into account uppercase letters in directories but that exercise is up to you.
You could do this with a recursive function.
function renameFiles($dir){
$files = scandir($dir);
foreach($files as $key=>$name){
if($name == '..' || $name == '.') continue;
if(is_dir("$dir/$name"))
renameFiles("$dir/$name");
else{
$oldName = $name;
$newName = strtolower($name);
rename("$dir/$oldName", "$dir/$newName");
}
}
}
This basically loops through a directory, if something is a file it renames it, if something is a directory it runs itself on that directory.
Try like that
public function renameFiles($dir)
{
$files = scandir($dir);
foreach ($files as $key => $name) {
if (is_dir("$dir/$name")) {
if ($name == '.' || $name == '..') {
continue;
}
$this->renameFiles("$dir/$name");
} else {
$oldName = $name;
$newName = strtoupper($name);
rename("$dir/$oldName", "$dir/$newName");
}
}
}
I want to create new folder for images dynamically, when one directory gets 1000 images in there Using PHP, MySQL what is best practice to achieve this kind of thing? :) Thanks
To count the number of files within a folder, I refer you to this answer.
You would then use the mkdir() function to create a new directory.
So you would have something like:
$directory = 'images';
$files = glob($directory . '*.jpg');
if ( $files !== false )
{
$filecount = count( $files );
if ($filecount >= 1000)
{
mkdir('images_2');
}
}
From this example Count how many files in directory php
Add an if statement that will create a folder when files reach a certain number
<?php
$dir = opendir('uploads/'); # This is the directory it will count from
$i = 0; # Integer starts at 0 before counting
# While false is not equal to the filedirectory
while (false !== ($file = readdir($dir))) {
if (!in_array($file, array('.', '..') and !is_dir($file)) $i++;
if($i == 1000) mkdir('another_folder');
}
echo "There were $i files"; # Prints out how many were in the directory
?>
define("IMAGE_ROOT","/images");
function getLastFolderID(){
$directory = array_diff( scandir( IMAGE_ROOT ), array(".", "..") );
//if there is empty root, return zero. Else, return last folder name;
$id = empty($directory) ? 0 : intval( end($directory) );
return $id;
}
$last_dir = getLastFolderID();
$target_path = IMAGE_ROOT . DIRECTORY_SEPARATOR . $last_dir;
$file_count = count( array_diff( scandir( $target_path ), array(".", "..") ) ); // exclude "." and ".."
//large than 1000 or there is no folder
if( $file_count > 1000 || $last_dir == 0){
$new_name = getLastFolderID() + 1;
$new_dir = IMAGE_ROOT . DIRECTORY_SEPARATOR . $new_name;
if( !is_dir($new_dir) )
mkdir( $new_dir );
}
I use these code at my website, FYR
So i solved my problem like this.
i'm using laravel for my php development.
first thing i'm getting last pictures folder and then checking if there is more then 1000 images.
if so i'm creating new folder with current date time.
code looks like this.
// get last image
$last_image = DB::table('funs')->select('file')
->where('file', 'LIKE', 'image%')
->orderBy('created_at', 'desc')->first();
// get last image directory
$last_image_path = explode('/', $last_image->file);
// last directory
$last_directory = $last_image_path[1];
$fi = new FilesystemIterator(public_path('image/'.$last_directory), FilesystemIterator::SKIP_DOTS);
if(iterator_count($fi) > 1000){
mkdir(public_path('image/fun-'.date('Y-m-d')), 0777, true);
$last_directory = 'fun-'.date('Y-m-d');
}
you can try something like this
$dir = "my_img_folder/";
if(is_dir($dir)) {
$images = glob("$dir{*.gif,*.jpg,*.JPG,*.png}", GLOB_BRACE); //you can add .gif or other extension as well
if(count($images) == 1000){
mkdir("/path/to/my/dir", 0777); //make the permission as per your requirement
}
}
I'm got a small PHP project that requires using files with numbered names, like so:
folder/1.file
folder/2.file
folder/3.file
... etc.
What I need to do is get an array of these filenames (easy enough), and then strip them down to integers (eg: array( 1, 2, 3 )). I'm a novice at PHP so I'm not up to speed on it's string functionality.
Any advice you could give me would be appreciated. Thank you.
Something like this should work:
$di = new DirectoryIterator('path/to/files');
foreach($di as $finfo) {
if($finfo->isFile()) {
$fname = (int)$finfo->getBasename();
// do something
}
}
$fname inside the foreach loop will contain your integer.
$array = array();
foreach(glob('*.file') as $filename) {
$array[] = (int)$filename;
}
print_r($array);
<?php
$files = array();
foreach($scandir('folder') as $file) {
if ($file == '.' || $file == '..')
continue;
$files[] = (int)$file;
}
This casts the filenames to an integer, which effectively changes anything that starts with an integer followed by any characters to just the integer.
e.g.
"123text" => 123
"421" => 421
"other" => 0
$directory = 'your/directory';
if ($handle = opendir($directory))
{
while (false !== ($file = readdir($handle)))
{
if ($file != "." && $file != ".." && is_file($directory . "/" . $file))
{
$file_id = (int)pathinfo($directory . "/" . $file,PATHINFO_FILENAME);
}
}
closedir($handle);
}
This should work fine.
You can use a regular expression:
foreach(scandir('/path/to/folder') as $file) {
$files[] = preg_replace("/[^0-9]+/", "", $file);
}
I have a folder. I want to put every file in this folder into an array and afterwards I want to echo them all in an foreach loop.
What's the best way to do this?
Thanks!
Scandir is what you're looking for
http://php.net/manual/en/function.scandir.php
<?php
$dir = '/tmp';
$files1 = scandir($dir);
print_r($files1);
?>
Or use combination of opendir and readdir
http://php.net/manual/en/function.readdir.php
Doesn't get much easier than this
http://ca3.php.net/manual/en/function.scandir.php
Don't forget to filter out hidden and parent directories (they start with a dot) on linux.
An Alternative:
define('PATH', 'files/');
$filesArray = array();
$filesArray = glob(PATH . '*', GLOB_ONLYDIR);
This method allow you to specify/filter a by file type. E.G.,
define('PATH', 'files/');
define('FILE_TYPE', '.jpg');
$filesArray = array();
$filesArray = glob(PATH . '*' . FILE_TYPE, GLOB_ONLYDIR);
You can also get the FULL path name to the file by removing the parameter 'GLOB_ONLYDIR'
This works for files and folders in subfolders too. Return list of folders and list of files with their path.
$dir = __DIR__; //work only for this current dir
function listFolderContent($dir,$path=''){
$r = array();
$list = scandir($dir);
foreach ($list as $item) {
if($item!='.' && $item!='..'){
if(is_file($path.$item)){
$r['files'][] = $path.$item;
}elseif(is_dir($path.$item)){
$r['folders'][] = $path.$item;
$sub = listFolderContent($path.$item,$path.$item.'/');
if(isset($sub['files']) && count($sub['files'])>0)
$r['files'] = isset ($r['files'])?array_merge ($r['files'], $sub['files']):$sub['files'];
if(isset($sub['folders']) && count($sub['folders'])>0)
$r['folders'] = array_merge ($r['folders'], $sub['folders']);
}
}
}
return $r;
}
$list = listFolderContent($dir);
var_dump($list['files']);
var_dump($list['folders']);
Edit: dwich answer is better. I will leave this just for information.
readdir.
<?php
if ($handle = opendir('/path/to/dir')) {
echo "Directory handle: $handle\n";
echo "Files:\n";
while (false !== ($file = readdir($handle))) {
echo "$file\n";
}
closedir($handle);
}
?>
Hope this helps.
—Alberto
If you scan a folder containing other folders AND files, how do you get rid of . and .. and files? How do you put in array only folders WITHOUT . and ..?
I would like to use regular expression, but I'm newbie and I can't get it right.
My code is now this but doesn't work:
if(fnmatch("\.{1,2}",$dir_array[$i]) || is_file($dir_array[$i]){
unset($dir_array[$i]);
}else{
//other code
}
You are confusing fnmatch and regular expressions in your code. To get all files and directories except the special ones, use this:
$dir_array = array_diff($dir_array, array(".", ".."));
Alternatively, if you iterate the array anyway, you can test each element like this:
foreach ($dir_array as $name) {
if (($name != "..") && ($name != ".")) {
// Do stuff on all files and directories except . ..
if (is_dir($name)) {
// Do stuff on directories only
}
}
}
In php<5.3, you can exclusively use a callback function, too:
$dir_array = array_filter($dir_array,
create_function('$n', 'return $n != "." && $n != ".." && is_dir($n);'));
(See Allain Lalonde's answer for a more verbose version)
Since php 5.3, this can be written nicer:
$dir_array = array_filter($dir_array,
function($n) {return $n != "." && $n != ".." && is_dir($n);});
Finally, combining array_filter and the first line of code of this answer yields an (insignificantly) slower, but probably more readable version:
$dir_array = array_filter(array_diff($dir_array, array(".", "..")), is_dir);
You don’t need a regular expression to test this. Just use plain string comparison:
if ($dir_array[$i] == '.' || $dir_array[$i] == '..' || is_file($dir_array[$i])) {
unset($dir_array[$i]);
}
no regex is needed, just unset() the first two values.
$d = dir($dir);
unset($d[0]);
unset($d[1]);
This may do it.
function is_not_meta_dir($file_name) {
// return true if $filename matches some pattern.
// without knowing the format of your $dir_array
return $file_name != '.' && $file_name != '..';
}
$new_dir_array = array_filter($dir_array, 'is_not_meta_dir');
I would do it like this:
$items = array();
$handle = opendir('path/to/dir');
while (($item = readdir($handle)) !== false) {
if (! in_array($item, array('.', '..'))) {
$items[] = $item;
}
}
closedir($handle);
print_r($items);
Although, I'd rather prefer DirectoryFilterDots but it's kind of rare in the available PHP distributions.
I'd do something like this (code may not work without effort since I haven't worked in PHP for years)
<?
if ($handle = opendir('/myPath'))
{
while (false !== ($file = readdir($handle)))
{
if (bool is_dir ( $file ) && substring($file,0,1) != ".")
{
$filesArray[] = $file; // this is the bit I'm not sure of the syntax for.
}
}
}
?>
EDIT misread the question - This should now add to the array all the folder names ion myPath that are not "." or ".."
$pathsArr = array();
foreach (explode($dirSeparator, $currentPath) as $path) {
if (strlen($path) && $path !== '.') {
if ($path === '..') {
// die('.....');
array_pop($pathsArr);
} else {
$pathsArr[] = $path;
}
}
}
$realpath = $winDrive . $dirSeparator . implode($dirSeparator, $pathsArr);