I am wondering how I can create a function that states:
if a file of name Setup.php exist twice in a folder and/or it's associated sub folders, return a message. if a file with the extension .css exists more then once in a folder or any of its sub folders, return a message
This function would have to be recursive, due to sub folders. and its fine to hard code 'Setup.php' or '.css' as they are the only things looked for.
What I currently have is a bit messy but does the trick (refactoring will come after I figure out this issue)
protected function _get_files($folder_name, $type){
$actual_dir_to_use = array();
$array_of_files[] = null;
$temp_array = null;
$path_info[] = null;
$array_of_folders = array_filter(glob(CUSTOM . '/' .$folder_name. '/*'), 'is_dir');
foreach($array_of_folders as $folders){
$array_of_files = $this->_fileHandling->dir_tree($folders);
if(isset($array_of_files) && !empty($array_of_files)){
foreach($array_of_files as $files){
$path_info = pathinfo($files);
if($type == 'css'){
if($path_info['extension'] == 'css'){
$actual_dir_to_use[] = $folders;
}
}
if($type == 'php'){
if($path_info['filename'] == 'Setup' && $path_info['extension'] == 'php'){
$temp_array[] = $folders;
$actual_dir_to_use[] = $folders;
}
}
}
}
$array_of_files = array();
$path_info = array();
}
return $actual_dir_to_use;
}
if you pass in say, packages and php into the function I will look through the packages folder and return all the sub-folder names, (eg: path/to/apples, path/to/bananas, path/to/fruit, path/to/cat, path/to/dog) that contain Setup with an extension of php.
The problem is if apples/ contains more then one Setup.php then I get: path/to/apples, path/to/apples, path/to/bananas, path/to/fruit, path/to/cat, path/to/dog
So I need to modify this function, or write a separate one, that sates the above sudo code.
problem? I don't know where to begin. So I am here asking for help.
You can find the class ipDirLiterator here - deleting all files in except the one running the delete code.
i hope you got it.
<?php
$directory = dirname( __FILE__ )."/test/";
$actual_dir_to_use = array();
$to_find = "php";
$literator = new ipDirLiterator( $directory, array( "file" => "file_literator", "dir" => "dir_literator" ) );
$literator->literate();
function file_literator( $file ) {
global $actual_dir_to_use, $to_find;
// use print_r( $file ) to see what all are inside $file
$filename = $file["filename"]; // the file name
$filepath = $file["pathname"]; // absolute path to file
$folder = $file["path"]; // the folder where the current file contains
$extens = strtolower( $file["extension"] );
if ( $to_find === "php" && $filename === "Setup.php" ) {
$actual_dir_to_use[] = $folder;
}
if ( $to_find === "css" && $extens === "css" ) {
$actual_dir_to_use[] = $folder;
}
}
function dir_literator( $file ) {}
print_r( $actual_dir_to_use );
// or check
if ( count( $actual_dir_to_use ) > 1 ) {
// here multiple files
}
?>
Q: Is this a homework assignment?
Assuming "no", then:
1) No, the function doesn't need to be recursive
2) Under Linux, you could find matching files like this: find /somefolder -name somefile -print
3) Similarly, you can detect if a match occurs zero, once or more than once in the path like this:
find /somefolder -name somefile -print|wc -l
Related
for a filemanagement i want to make an anchor for scanning a specific directory.
I use this echo for it:
echo "<div class='urldir'>"
."<a href='?dir=".dirname($dir).'/'.basename($dir).'/'.$file."'>open dir</a>"
."</div>";
The dirname and basename give me the the right path to the directory.
this is the normal "root" directory for the users:
$dir = 'uploads/sfm/'.$UserID;
When i user created a folder in his root, he must be able to see the files in that folder.To change the directory and show all the files in that directory, i use this
$actual_link = "http://$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]";
$strArr = explode("=",$actual_link);
$CurrentPath = $strArr[1];
if(isset($_GET['dir'])) {
$dir = $CurrentPath;
}
So i read the dir from the url and the variable $dir changes
The problem: the url shows me a string like this:
sfm?dir=uploads/sfm/c4ca4238a0b923820dcc509a6f75849b/folder
When i type now in the url:
sfm?dir=uploads/
he shows me the files in uploads folder. This must be protected!
Nobody should be able to see this.
And also this must be protected from view:
sfm?dir=uploads/sfm/
How can i achieve that?
By the way: the hash in the url is because i have the var $UserID md5 hashed
md5($UserID)
$protectedDirectories = array(
array( 'uploads', 'sfm', $userId )
);
$directory = str_replace('\\','',$_GET['dir']);
$directory = trim($directory,'/');
$directory = preg_replace('#[\/]{1,}#','/',$directory);
$stats = false; // True = Protected , False = Cannot enter this directory.
$seperate = explode('/',$directory);
$cntSeperate = count( $seperate );
foreach($protectedDirectories as $pattern ){
if( count( $pattern ) > $cntSeperate ){
continue;
}
$innerStats = true;
foreach( $pattern as $key => $val ){
if( $seperate[ $key ] !== $val ){
$innerStats = false;
break;
}
}
if( $innerStats == false ){
continue;
}
$stats = true;
break;
}
if( $stats == true ){
// Access Granted
}else{
// Access Not Granted
}
Now you can dynamically use your directory access grants. Each array means a pattern. Each array's value is a directory inside directories ( For example : array('uploads', 'sfm') means uploads/sfm )
A sample solution is to grab the md5 directory using a regular expression.
Something like this:
$res = preg_match('/uploads\/sfm\/([a-f0-9]{32}).*/', $dir, $matches);
if (!$res || $matches[1] != md5($UserID)) {
// user requested a directory he has no access to. Take additional
// actions, e.g. return HTTP status 403
exit('No access here');
}
I am taking over a website already build because the original programmer is not available anymore.
I need to rename files in a directory, then move the files to their own folder matching the file name, but if the folder does not exist I need to create the folder.
To rename the files I have this php code that it was using the original programmer of the website (Was tested and is working as expected, Let me clarify that the files are something like STV12543.htm and need to be 12543_Todays-Date.htm)
<?php
function dirList ($directory, $prefijo )
{
$results = array();
$handler = opendir($directory);
while ($file = readdir($handler)) {
$comienzo = substr($file, 0, 3);
if ($file != '.' && $file != '..' && $comienzo== $prefijo)
$results[] = $file;
}
closedir($handler);
return $results;
}
$directory = "ws/archivos-cli/";
$prefijo = "STV";
$resultado = dirList($directory, $prefijo);
foreach($resultado as $file){
$ultima_modificacion = filemtime($directory.$file);
$ultima_modificacion = date("Y-m-d", $ultima_modificacion);
$name = split('STV',$file);
$name = split('.htm',$name[1]);
$newname = $name[0].'_'.$ultima_modificacion.'.htm';
//if (!file_exists($directory.$newname))
rename($directory.$file, $directory.$newname);
}
?>
I guess I can call that scrip with a cron, but for moving files, I have a sh script
#!/bin/sh
source_dir='/ws/archivos-cli/'
target_dir='/ws/archivos-cli/subfolders'
name_separator='_'
(
cd ${source_dir} || {
echo "${source_dir} no existe!" ; exit 1
}
for i in `ls` ; do
client_name="`echo ${i} | cut -f1 -d${name_separator}`"
echo "-> Moving file [${i}] to [${target_dir}/${client_name}/] folder"
mv -vf ${i} ${target_dir}/${client_name}/ || break
echo
done
)
So, how can I combine them (the 2 scripts) and add the option to create the folder if not exists, based on the file name without the date?
Thank you in advance.
How to use php keep only specific file and remove others in directory?
example:
1/1.png, 1/2.jpeg, 1/5.png ...
the file number, and file type is random like x.png or x.jpeg, but I have a string 2.jpeg the file need to keep.
any suggestion how to do this??
Thanks for reply, now I coding like below but the unlink function seems not work delete anything.. do I need change some setting? I'm using Mamp
UPDATE
// explode string <img src="u_img_p/5/x.png">
$content_p_img_arr = explode('u_img_p/', $content_p_img);
$content_p_img_arr_1 = explode('"', $content_p_img_arr[1]); // get 5/2.png">
$content_p_img_arr_2 = explode('/', $content_p_img_arr_1[0]); // get 5/2.png
print $content_p_img_arr_2[1]; // get 2.png < the file need to keep
$dir = "u_img_p/".$id;
if ($opendir = opendir($dir)){
print $dir;
while(($file = readdir($opendir))!= FALSE )
if($file!="." && $file!= ".." && $file!= $content_p_img_arr_2[1]){
unlink($file);
print "unlink";
print $file;
}
}
}
I change the code unlink path to folder, then it works!!
unlink("u_img_p/".$id.'/'.$file);
http://php.net/manual/en/function.scandir.php
This will get all files in a directory into an array, then you can run a foreach() on the array and look for patterns / matches on each file.
unlink() can be used to delete the file.
$dir = "/pathto/files/"
$exclude[] = "2.jpeg";
foreach(scandir($dir) as $file) {
if (!in_array($file, $exclude)) {
unlink("$dir/$file");
}
}
Simple and to the point. You can add multiple files to the $exclude array.
$dir = "your_folder_path";
if ($opendir = opendir($dir)){
//read directory
while(($file = readdir($opendir))!= FALSE ){
if($file!="." && $file!= ".." && $file!= "2.jpg"){
unlink($file);
}
}
}
function remove_files( $folder_path , $aexcludefiles )
{
if (is_dir($folder_path))
{
if ($dh = opendir($folder_path))
{
while (($file = readdir($dh)) !== false)
{
if( $file == '.' || $file == '..' )
continue ;
if( in_array( $file , $aexcludefiles ) )
continue ;
$file_path = $folder_path."/".$file ;
if( is_link( $file_path ) )
continue ;
unlink( $file_path ) ;
}
closedir($dh);
}
}
}
$aexcludefiles = array( "2.jpeg" )
remove_files( "1" , $aexcludefiles ) ;
I'm surprised people don't use glob() more. Here is another idea:
$dir = '/absolute/path/to/u_img_p/5/';
$exclude[] = $dir . 'u_img_p/5/2.jpg';
$filesToDelete = array_diff(glob($dir . '*.jpg'), $exclude);
array_map('unlink', $filesToDelete);
First, glob() returns an array of files based on the pattern provided to it. Next, array_diff() finds all the elements in the first array that aren't in the second. Finally, use array_map() with unlink() to delete all but the excluded file(s). Be sure to use absolute paths*.
You could even make it into a helper function. Here's a start:
<?php
/**
* #param string $path
* #param string $pattern
* #param array $exclude
* #return bool
*/
function deleteFiles($path, $pattern, $exclude = [])
{
$basePath = '/absolute/path/to/your/webroot/or/images/or/whatever/';
$path = $basePath . trim($path, '/');
if (is_dir($path)) {
array_map(
'unlink',
array_diff(glob($path . '/' . $pattern, $exclude)
);
return true;
}
return false;
}
unlink() won't work unless the array of paths returned by glob() happen to be relative to where unlink() is called. Since glob() will return only what it matches, it's best to use the absolute path of the directory in which your files to delete/exclude are contained.See the docs and comments on how glob() matches and give it a play to see how it works.
Is there a way I could use php to make root file to look like its also in other folders too.
For example I have index.php in root folder and I want it to be like that when I access index.php then it could also behave as its in all the folders and subfolders too
When I execute index.php then it will also execute in all folders and subfolders too
Please understand my question by the example below
index.php is in root and I have different folders in root as well so when I access the index.php through browser then it will also execute in other folders
http://mysite.com/index.php will also behave as if its in sub folder too
http://mysite.com/folder1/index.php
http://mysite.com/folder2/index.php
http://mysite.com/folder3/index.php
index.php is not in these folders but it must execute in these folders too at the same time
I think its not difficult to understand through above examples.please answer accordingly
Update 2
Here is the index.php code
It scans the folders "files" "images" "txt" "related" and get the files in each folder and then it writes to the includes.php (in root)
$path = array("./files/","./images/","./txt/","./related/");
$path2= array("http://".$_SERVER['SERVER_NAME'].dirname($_SERVER["PHP_SELF"])."/files/","http://".$_SERVER['SERVER_NAME'].dirname($_SERVER["PHP_SELF"])."/images/","http://".$_SERVER['SERVER_NAME'].dirname($_SERVER["PHP_SELF"])."/txt/","http://".$_SERVER['SERVER_NAME'].dirname($_SERVER["PHP_SELF"])."/related/");
$start="";
$Fnm = "./include.php";
$inF = fopen($Fnm,"w");
fwrite($inF,$start."\n");
$folder = opendir($path[0]);
while( $file = readdir($folder) ) {
if (($file != '.')&&($file != '..')&&($file != 'index.htm')) {
$folder2 = opendir($path[1]);
$folder3 = opendir($path[2]);
$folder4 = opendir($path[3]);
$imagename ='';
$txtname ='';
$related ='';
while( $file2 = readdir($folder2) ) {
if (substr($file2,0,strpos($file2,'.')) == substr($file,0,strpos($file,'.'))){
$imagename = $file2;
}
}
while( $file4 = readdir($folder4) ) {
if (substr($file4,0,strpos($file4,'.')) == substr($file,0,strpos($file,'.'))){
$related = $file4;
}
}
while( $file3 = readdir($folder3) ) {
if (substr($file3,0,strpos($file3,'.')) == substr($file,0,strpos($file,'.'))){
$txtname = $file3;
$fh = fopen("/home3/socialb8/public_html/mysite.info/player/txt/$txtname", 'r');
$theData = fread($fh, filesize("/home3/socialb8/public_html/mysite.info/player/txt/$txtname"));
fclose($fh);
}
}
closedir($folder2);
closedir($folder3);
closedir($folder4);
$result="{\nlevels: [\n{ file: \"$path2[0]$file\" }\n],\nimage: \"$path2[1]$imagename\",\ntitle: \"$file\",\ndescription: \"$theData\",\n 'related.file':'$path2[3]$related'\n},\n";
fwrite($inF,$result);
}
}
fwrite($inF,"");
closedir($folder);
fclose($inF);
If you need to cycle through the directories and see if each of those directories contains one of the directories listed in the $path array you could use something like:
function readDirs()
{
$path=array('images','etc...');
$dirHandle = opendir('./');
while($file = readdir($dirHandle))
{
if(is_dir($file) && $file != '.' && $file != '..')
{
$dirHandle2 = opendir($file);
while($file2 = readdir($dirHandle2))
{
if(in_array($file2,$path))
{
// do what you need to do
}
}
}
}
}
readDirs();
That will cycle through all the directories in the root folder and see if they contain a directory listed in the $path array, if so you can pop your code in the // do what you need to do statement.
Hope that helps!
I have an array that lists folders in a directory. Until now, I've been hardcoding the folder names, but rather than do that, I thought I could easily create a script to parse the directory and just assign each folder name to the array. That way, I could easily add folders and not have to touch the script again...
The subject array creates an options list pulldown menu listing each folder...
Currently, the array is hardcoded like so...
"options" => array("folder one" => "folder1", "folder two" => "folder2")),
But I'm trying to make it dynamic based on whatever folders it finds in the given directory.
Here's the script I'm using to parse the directory and return the foldernames to the array. It works fine.
function getDirectory( $path = '.', $level = 0 )
{
// Directories to ignore when listing output.
$ignore = array( '.', '..' );
// Open the directory to the handle $dh
$dh = #opendir( $path );
// Loop through the directory
while( false !== ( $file = readdir( $dh ) ) )
{
// Check that this file is not to be ignored
if( !in_array( $file, $ignore ) )
{
// Show directories only
if(is_dir( "$path/$file" ) )
{
// Re-call this same function but on a new directory.
// this is what makes function recursive.
//echo $file." => ".$file. ", ";
// need to return the folders in the form expected by the array. Probably could just add the items directly to the array?
$mydir2=$mydir2.'"'.$file.'" => "'.$file. '", ';
getDirectory( "$path/$file", ($level+1) );
}
}
}
return $mydir2;
// Close the directory handle
closedir( $dh );
}
And here's my first take at getting those folders into the array...
$mydir = getDirectory('/images/');
"options" => array($mydir)),
But obviously, that doesn't work correctly since its not feeding the array properly I just get a string in my options list... I'm sure this is an easy conversion step I'm missing...
Why not just look at php.net? It has several examples on recursive dir listing.
Here is one example:
<?php
public static function getTreeFolders($sRootPath = UPLOAD_PATH_PROJECT, $iDepth = 0) {
$iDepth++;
$aDirs = array();
$oDir = dir($sRootPath);
while(($sDir = $oDir->read()) !== false) {
if($sDir != '.' && $sDir != '..' && is_dir($sRootPath.$sDir)) {
$aDirs[$iDepth]['sName'][] = $sDir;
$aDirs[$iDepth]['aSub'][] = self::getTreeFolders($sRootPath.$sDir.'/',$iDepth);
}
}
$oDir->close();
return empty($aDirs) ? false : $aDirs;
}
?>
You want to create an array, not a string.
// Replace
$mydir2=$mydir2.'"'.$file.'" => "'.$file. '", ';
// With
$mydir2[$file] = $file;
Also, close $dh before returning. Now, closedir is never called.
Here is a simple function that will return an array of available directories, but it is not recursive in that it has a limited depth. I like it because it is so simple:
<?php
function get_dirs( $path = '.' ){
return glob(
'{' .
$path . '/*,' . # Current Dir
$path . '/*/*,' . # One Level Down
$path . '/*/*/*' . # Two Levels Down, etc.
'}', GLOB_BRACE + GLOB_ONLYDIR );
}
?>
You can use it like this:
$dirs = get_dirs( WP_CONTENT_DIR . 'themes/clickbump_wp2/images' );
If you're using PHP5+ you might like scandir(), which is a built-in function that seems to do pretty much what you're after. Note that it lists all the entries in a folder - files, folders, . and .. included.