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.
Related
A little stuck on this and hoping for some help. I'm trying to get the last modified dir from a path in a string. I know there is a function called "is_dir" and I've done some research but can't seem to get anything to work.
I don't have any code i'm sorry.
<?php
$path = '../../images/';
// echo out the last modified dir from inside the "images" folder
?>
For example: The path variable above has 5 sub folders inside the "images" dir currently right now. I want to echo out "sub5" - which is the last modified folder.
You can use scandir() instead of is_dir() function to do it.
Here is an example.
function GetFilesAndFolder($Directory) {
/*Which file want to be escaped, Just add to this array*/
$EscapedFiles = [
'.',
'..'
];
$FilesAndFolders = [];
/*Scan Files and Directory*/
$FilesAndDirectoryList = scandir($Directory);
foreach ($FilesAndDirectoryList as $SingleFile) {
if (in_array($SingleFile, $EscapedFiles)){
continue;
}
/*Store the Files with Modification Time to an Array*/
$FilesAndFolders[$SingleFile] = filemtime($Directory . '/' . $SingleFile);
}
/*Sort the result as your needs*/
arsort($FilesAndFolders);
$FilesAndFolders = array_keys($FilesAndFolders);
return ($FilesAndFolders) ? $FilesAndFolders : false;
}
$data = GetFilesAndFolder('../../images/');
var_dump($data);
From above example the last modified Files or Folders will show as Ascending order.
You can also separate your files and folder by checking is_dir() function and store the result in 2 different arrays like $FilesArray=[] and $FolderArray=[].
Details about filemtime() scandir() arsort()
Here's one way you can accomplish this:
<?php
// Get an array of all files in the current directory.
// Edit to use whatever location you need
$dir = scandir(__DIR__);
$newest_file = null;
$mdate = null;
// Loop over files in directory and if it is a subdirectory and
// its modified time is greater than $mdate, set that as the current
// file.
foreach ($dir as $file) {
// Skip current directory and parent directory
if ($file == '.' || $file == '..') {
continue;
}
if (is_dir(__DIR__.'/'.$file)) {
if (filemtime(__DIR__.'/'.$file) > $mdate) {
$newest_file = __DIR__.'/'.$file;
$mdate = filemtime(__DIR__.'/'.$file);
}
}
}
echo $newest_file;
This will work too just like the other answers. Thanks everyone for the help!
<?php
// get the last created/modified directory
$path = "images/";
$latest_ctime = 0;
$latest_dir = '';
$d = dir($path);
while (false !== ($entry = $d->read())) {
$filepath = "{$path}/{$entry}";
if(is_dir($filepath) && filectime($filepath) > $latest_ctime) {
$latest_ctime = filectime($filepath);
$latest_dir = $entry;
}
} //end loop
echo $latest_dir;
?>
I'm using bootstrap tables and rows to count how much files are in a folder, but the destination is pointing to a different server the code below does not work.
As i'm using localhost (xampp) trying to do this don't know if its possible.
<?php
// integer starts at 0 before counting
$i = 0;
$dir = 'uploads/'; <!--\\189.207.00.122\folder1\folder2\folder3\test-->
if ($handle = opendir($dir)) {
while (($file = readdir($handle)) !== false){
if (!in_array($file, array('.', '..')) && !is_dir($dir.$file))
$i++;
}
}
// prints out how many were in the directory
echo "There were $i files";
?>
Here is a handy little function you might want to try out. Just pass the path to the Directory as the first argument to it and you'd get your result.
NOTE: This Function is RECURSIVE, which means: it will traverse all sub-directories... to disable this behaviour, simply comment out or delete the following lines towards the end of the Funciton:
<?php
}else if(is_dir($temp_file_or_dir) && !preg_match('/^\..*/', $val) ){
getFilesInFolder($temp_file_or_dir);
}
THE CODE:
<?php
$folder = dirname(__FILE__).'/uploads'; // ASSUMES YOUR uploads DIRECTORY
// IS IN THE SAME DIRECTORY AS index.php
// (/htdocs/php/pages)
// OR
$folder = dirname(__FILE__).'/../uploads'; // ASSUMES YOUR uploads DIRECTORY
// IS ONE DIRECTORY ABOVE
// THE CURRENT DIRECTORY (/htdocs/php)
// THIS IS MOST LIKELY RIGHT
// OR
$folder = dirname(__FILE__).'/../../uploads';// ASSUMES YOUR uploads DIRECTORY
// IS TWO DIRECTORIES ABOVE
// THE CURRENT DIRECTORY (/htdocs)
// MAKE SURE THE FOLDER IN QUESTION HAS THE RIGHT PERMISSIONS
// OR RATHER CHANGE PERMISSIONS ON THE FOLDER TO BE ABLE TO WORK WITH IT
chmod($folder, 0777);
var_dump(getFilesInFolder($folder));
// IF YOU PASS false AS THE THE 2ND ARGUMENT TO THIS FUNCTION
// YOU'D GET AN ARRAY OF ALL FILES IN THE $path2Folder DIRECTORY
// AS WELL AS IN SUB-DIRECTORIES WITHIN IT...
function getFilesInFolder($path2Folder, $countOnly=true){
$files_in_dir = scandir($path2Folder);
$returnable = array();
foreach($files_in_dir as $key=>$val){
$temp_file_or_dir = $path2Folder . DIRECTORY_SEPARATOR . $val;
if(is_file($temp_file_or_dir) && !preg_match("#^\..*#", $temp_file_or_dir)){
$arrRX = array('#\.{2,4}$#', '#\.#');
$arrReplace = array("", "_");
$returnVal = preg_replace($arrRX, $arrReplace, $val);
$returnable[$returnVal] = $temp_file_or_dir;
}else if(is_dir($temp_file_or_dir) && !preg_match('/^\..*/', $val) ){
getFilesInFolder($temp_file_or_dir);
}
}
return ($countOnly) ? count($returnable) : $returnable;
}
Use $_SERVER['DOCUMENT_ROOT'] to get your root directory.
$dir = $_SERVER['DOCUMENT_ROOT'].'/uploads/';
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
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 a script that opens a directory, checks if the folders matches an array, and then opens them.
In the directory there is a list of folders like "apache2-50", but when the script opens that folder, it only displays the .DS_Store file. Here is the output:
This-is-not-a-MacBook:backend code archangel$ php -f frolic.php "/Users/archangel/Desktop/Httpbench Files/results"
Test Found apache2 in directory /Users/archangel/Desktop/Httpbench Files/results/apache2-50
--/Users/archangel/Desktop/Httpbench Files/results/apache2-50/.DS_Store
But here is the directory listing:
This-is-not-a-MacBook:apache2-50 archangel$ ls
0 1 2
Now what I am trying to figure out why my php script is not showing those folders. When I change the folder "0" to "3" it works:
This-is-not-a-MacBook:apache2-50 archangel$ ls
1 2 3
This-is-not-a-MacBook:backend code archangel$ php -f frolic.php "/Users/archangel/Desktop/Httpbench Files/results"
Test Found apache2 in directory /Users/archangel/Desktop/Httpbench Files/results/apache2-50
--/Users/archangel/Desktop/Httpbench Files/results/apache2-50/.DS_Store
--/Users/archangel/Desktop/Httpbench Files/results/apache2-50/1
--/Users/archangel/Desktop/Httpbench Files/results/apache2-50/2
--/Users/archangel/Desktop/Httpbench Files/results/apache2-50/3
Here is the code that I am running:
#!/bin/php
//...
$dir = opendir($argv[1]);
//Opened the directory;
while($file = readdir($dir)){
//Loops through all the files/directories in our directory;
if($file!="." && $file != ".."){
$f = explode("-", $file);
if(in_array($f[0], $servers) and in_array($f[1], $tests)) {
echo "Test Found $f[0] in directory $argv[1]/$f[0]-$f[1]\n";
$sdir = opendir("$argv[1]/$f[0]-$f[1]");
while($sfile = readdir($sdir)){
if($sfile!="." && $sfile != ".."){
echo "--$argv[1]/$f[0]-$f[1]/$sfile\n";
}
}
}
}
}
Could this be something wong with my script, or a bug in php(PHP 5.3.3)?
Thanks
This is a (very nasty) side effect of the string "0" evaluating to false in PHP. When that happens, your while loop
while($file = readdir($dir))
will break.
This should work, because it breaks only when readdir() actually returns false:
while(($file = readdir($dir)) !== false)
(obviously, change both loops accordingly, not just the outer one.)
Why are you using opendir at all? I think glob would be a little easier to use:
$files = glob("$argv[1]/*-*/*");
foreach($files as $file) {
$parts = explode("/", $file);
// get the directory part
$f = explode("-", $parts[count($parts) - 2]);
if(in_array($f[0], $servers) and in_array($f[1], $tests)) {
echo "Test Found $f[0] in directory $argv[1]/$f[0]-$f[1]\n";
echo "--$argv[1]/$f[0]-$f[1]/$sfile\n";
}
}
Replace
while($sfile = readdir($sdir)){
with
while(($sfile = readdir($sdir)) !== 0){
Otherwise when filename is 0, $sfile is "0" which is translated to false. By using !== or === you are forcing a type check between the variables so that "0" does not equal 0.