PHP CLI: Recursive Search and Replace: Difference between revisions

no edit summary
(New page: {{Uc nav PHP CLI}} '''''PHP CLI Recursive Search and Replace''''' On the previous page I covered single file search and replace although adequate for most applications occasionally you wi...)
 
No edit summary
Line 1: Line 1:
=[http://aluxyxenud.co.cc This Page Is Currently Under Construction And Will Be Available Shortly, Please Visit Reserve Copy Page]=
{{Uc nav PHP CLI}}
{{Uc nav PHP CLI}}
'''''PHP CLI Recursive Search and Replace'''''
'''''PHP CLI Recursive Search and Replace'''''
Line 13: Line 14:
|-
|-
|
|
'''''Run.bat'''''|| 
'''''Run.bat'''''|| 
|-valign="top"
|-valign="top"
|
|
<pre>
&lt;pre&gt;
TITLE CLI TEST BAT
TITLE CLI TEST BAT
COLOR B0
COLOR B0
Line 25: Line 26:
echo.
echo.
pause
pause
</pre>
&lt;/pre&gt;
|
|
<br>
&lt;br&gt;
Batch file to run test_1.php script
Batch file to run test_1.php script


Line 36: Line 37:
All scripts on this page will require the above change.
All scripts on this page will require the above change.
|-
|-
|'''''test_1.php'''''||&nbsp;
|'''''test_1.php'''''||&amp;nbsp;
|-valign="top"
|-valign=&quot;top&quot;
|
|
<pre>
&lt;pre&gt;
<?php
&lt;?php
$sfolder = "./usr/local/mysql";        // Start folder
$sfolder = &quot;./usr/local/mysql&quot;;        // Start folder


$Array=recur_dir($sfolder);            // Retrieve file list
$Array=recur_dir($sfolder);            // Retrieve file list


foreach($Array as $line){              // Print list
foreach($Array as $line){              // Print list
  echo $line."\n";
  echo $line.&quot;\n&quot;;
}
}


Line 64: Line 65:
//========================================== END Recursive Directory =====
//========================================== END Recursive Directory =====
exit(0);
exit(0);
?>
?&gt;
</pre>
&lt;/pre&gt;
|
|
* First line sets the initial starting folder in variable '''$sfolder'''
* First line sets the initial starting folder in variable '''$sfolder'''
Line 73: Line 74:
* The recursive function takes as parameter the starting directory '''$dir'''  
* The recursive function takes as parameter the starting directory '''$dir'''  
* opendir() opens a handle to the starting directory and saves it in variable $dirlist  
* opendir() opens a handle to the starting directory and saves it in variable $dirlist  
* readdir() function returns a single entry from the currently open directory and saves it in variable $file.<br>'''''Note'':''' The returned value is either name of a directory or name of a file including its file extension.
* readdir() function returns a single entry from the currently open directory and saves it in variable $file.&lt;br&gt;'''''Note'':''' The returned value is either name of a directory or name of a file including its file extension.
* The while loop is use to read every single entry in the open directory until there are no more entries to read.
* The while loop is use to read every single entry in the open directory until there are no more entries to read.
* Inside the while loop the full path is assembled and assigned to variable '''$newpath'''. This is added to the array '''$Array[]'''
* Inside the while loop the full path is assembled and assigned to variable '''$newpath'''. This is added to the array '''$Array[]'''
Line 80: Line 81:
Run the batch file (double click on '''Run.bat''') Result as follows:
Run the batch file (double click on '''Run.bat''') Result as follows:
{|
{|
|-valign="top"
|-valign=&quot;top&quot;
|
|
<pre>
&lt;pre&gt;
./usr/local/mysql/.
./usr/local/mysql/.
./usr/local/mysql/..
./usr/local/mysql/..
Line 90: Line 91:
./usr/local/mysql/share
./usr/local/mysql/share
Press any key to continue . . .
Press any key to continue . . .
</pre>
&lt;/pre&gt;
|
|
<br>
&lt;br&gt;
'''Well!''' What should be obvious there is no recursion, the code is only a starting point.
'''Well!''' What should be obvious there is no recursion, the code is only a starting point.


The output contains a mixture of folders (bin, data, share) and files (my.cnf, mysqlrun.bat, mysqlstop.bat, README.txt)
The output contains a mixture of folders (bin, data, share) and files (my.cnf, mysqlrun.bat, mysqlstop.bat, README.txt)


You will notice there are two special sub-directory names [.] and [..] these are normally hidden note that every folder contains them. A single period [.] means "the current default directory." Two periods [..] means "the directory which contains the current default directory" also known as the parent directory. They are useful for navigation however will cause problems if not removed from a directory listing.   
You will notice there are two special sub-directory names [.] and [..] these are normally hidden note that every folder contains them. A single period [.] means &quot;the current default directory.&quot; Two periods [..] means &quot;the directory which contains the current default directory&quot; also known as the parent directory. They are useful for navigation however will cause problems if not removed from a directory listing.   


|}
|}
Line 110: Line 111:
{|
{|
|-
|-
|'''''test_1.php'''''||&nbsp;
|'''''test_1.php'''''||&amp;nbsp;
|-valign="top"
|-valign=&quot;top&quot;
|
|
<pre>
&lt;pre&gt;
<?php
&lt;?php
$sfolder = "./usr/local/mysql";        // Start folder
$sfolder = &quot;./usr/local/mysql&quot;;        // Start folder
$Array=recur_dir($sfolder);            // Retrieve file list
$Array=recur_dir($sfolder);            // Retrieve file list


foreach($Array as $line){              // Print list
foreach($Array as $line){              // Print list
  echo $line."\n";
  echo $line.&quot;\n&quot;;
}
}
//=== Recursive Directory ==============================================
//=== Recursive Directory ==============================================
Line 127: Line 128:
   $dirlist = opendir($dir);            // Open start directory
   $dirlist = opendir($dir);            // Open start directory
   while ($file = readdir($dirlist)){    // Iterate through list
   while ($file = readdir($dirlist)){    // Iterate through list
     if ($file != '.' && $file != '..'){ // Skip if . or ..
     if ($file != '.' &amp;&amp; $file != '..'){ // Skip if . or ..
       $newpath = $dir.'/'.$file;        // Create path. Either dir or file  
       $newpath = $dir.'/'.$file;        // Create path. Either dir or file  


Line 144: Line 145:
//========================================== END Recursive Directory =====
//========================================== END Recursive Directory =====
exit(0);
exit(0);
?>
?&gt;
</pre>
&lt;/pre&gt;
|
|
* Within the while loop first check for one of the special sub-folders. If not either of these contue otherwise skip. Let the while loop pick up another entry.
* Within the while loop first check for one of the special sub-folders. If not either of these contue otherwise skip. Let the while loop pick up another entry.
Line 154: Line 155:
* Handle is closed using closedir($dirlist) and array returned to caller.  
* Handle is closed using closedir($dirlist) and array returned to caller.  
'''''Run''''' the batch file (double click on '''Run.bat''') Result as follows:
'''''Run''''' the batch file (double click on '''Run.bat''') Result as follows:
<pre>
&lt;pre&gt;
./udrive/usr/local/mysql/my.cnf
./udrive/usr/local/mysql/my.cnf
</pre>
&lt;/pre&gt;
'''''Well what a pain''!'''
'''''Well what a pain''!'''


Line 167: Line 168:
=== Modification ===
=== Modification ===
{|
{|
|-valign="top"
|-valign=&quot;top&quot;
|
|
<pre>
&lt;pre&gt;
  if (is_dir($newpath)){        // Is it a folder
  if (is_dir($newpath)){        // Is it a folder
   recur_dir($newpath);        // yes: Repeat this function
   recur_dir($newpath);        // yes: Repeat this function
   echo "Path = ".$newpath."\n";
   echo &quot;Path = &quot;.$newpath.&quot;\n&quot;;
  }                              // for that new folder
  }                              // for that new folder
</pre>
&lt;/pre&gt;
|
|
<br>
&lt;br&gt;
Add the '''echo''' line as shown to the above script.
Add the '''echo''' line as shown to the above script.


Line 186: Line 187:
=== Result ===
=== Result ===
{|
{|
|-valign="top"
|-valign=&quot;top&quot;
|
|
<pre>
&lt;pre&gt;


Path = ./usr/local/mysql/bin
Path = ./usr/local/mysql/bin
Line 201: Line 202:


Press any key to continue . . .
Press any key to continue . . .
</pre>
&lt;/pre&gt;
|
|
<br>
&lt;br&gt;
An interesting result, it clearly shows recursion is taking place.
An interesting result, it clearly shows recursion is taking place.


Line 228: Line 229:
{|
{|
|-
|-
|'''''test_1.php'''''||&nbsp;
|'''''test_1.php'''''||&amp;nbsp;
|-valign="top"
|-valign=&quot;top&quot;
|
|
<pre>
&lt;pre&gt;
<?php
&lt;?php
$sfolder = "./usr/local/mysql";  // Start folder
$sfolder = &quot;./usr/local/mysql&quot;;  // Start folder
$Array=recur_dir($sfolder);            // Retrieve file list
$Array=recur_dir($sfolder);            // Retrieve file list


foreach($Array as $line){              // Print list
foreach($Array as $line){              // Print list
  echo $line."\n";
  echo $line.&quot;\n&quot;;
}
}
//=== Recursive Directory ==============================================
//=== Recursive Directory ==============================================
    
    
function recur_dir($dir,&$Array){
function recur_dir($dir,&amp;$Array){


   $dirlist = opendir($dir);            // Open start directory
   $dirlist = opendir($dir);            // Open start directory
   while ($file = readdir($dirlist)){    // Iterate through list
   while ($file = readdir($dirlist)){    // Iterate through list
     if ($file != '.' && $file != '..'){ // Skip if . or ..
     if ($file != '.' &amp;&amp; $file != '..'){ // Skip if . or ..
       $newpath = $dir.'/'.$file;        // Create path. Either dir or file  
       $newpath = $dir.'/'.$file;        // Create path. Either dir or file  


Line 262: Line 263:
//========================================== END Recursive Directory =====
//========================================== END Recursive Directory =====
exit(0);
exit(0);
?>
?&gt;
</pre>
&lt;/pre&gt;
|
|
<br>
&lt;br&gt;
'''''Run''''' the batch file (double click on '''Run.bat''') Result as follows:
'''''Run''''' the batch file (double click on '''Run.bat''') Result as follows:


Line 275: Line 276:


We have seen this [[PHP CLI: User Input#Function variable parameters |'''before''']] the solution is to change this line:
We have seen this [[PHP CLI: User Input#Function variable parameters |'''before''']] the solution is to change this line:
<pre>
&lt;pre&gt;
function recur_dir($dir,&$Array){
function recur_dir($dir,&amp;$Array){
</pre>
&lt;/pre&gt;
'''To:'''
'''To:'''
<pre>
&lt;pre&gt;
function recur_dir($dir,&$Array=false){
function recur_dir($dir,&amp;$Array=false){
</pre>
&lt;/pre&gt;


Initial call to function pass a single parameter.
Initial call to function pass a single parameter.
Line 300: Line 301:
|-
|-
|
|
<pre>
&lt;pre&gt;
'/(\.txt|\.cnf|\.conf)/'
'/(\.txt|\.cnf|\.conf)/'
</pre>
&lt;/pre&gt;
|
|
Pattern is delimited using ''''/'''' The entire regex is enclosed between brackets allowing the vertical bar (special character meaning or) to be used. The period (full stop) is a special regex character hence requires escaping using a backslash.     
Pattern is delimited using ''''/'''' The entire regex is enclosed between brackets allowing the vertical bar (special character meaning or) to be used. The period (full stop) is a special regex character hence requires escaping using a backslash.     
Line 311: Line 312:
{|
{|
|-
|-
|'''''test_1.php'''''||&nbsp;
|'''''test_1.php'''''||&amp;nbsp;
|-valign="top"
|-valign=&quot;top&quot;
|
|
<pre>
&lt;pre&gt;
<?php
&lt;?php
$sfolder = "./usr/local";              // Start folder
$sfolder = &quot;./usr/local&quot;;              // Start folder
$File_list_array=recur_dir($sfolder);  // Retrieve file list
$File_list_array=recur_dir($sfolder);  // Retrieve file list


foreach($File_list_array as $line){    // Print list
foreach($File_list_array as $line){    // Print list
  echo $line."\n";
  echo $line.&quot;\n&quot;;
}
}
//=== Recursive Directory ==============================================
//=== Recursive Directory ==============================================
    
    
function recur_dir($dir,&$Array=false){
function recur_dir($dir,&amp;$Array=false){
   $f_str='/(\.txt|\.cnf|\.conf)/';        // Filter, required files
   $f_str='/(\.txt|\.cnf|\.conf)/';        // Filter, required files


Line 330: Line 331:


   while ($file = readdir($dirlist)){      // Iterate through list
   while ($file = readdir($dirlist)){      // Iterate through list
     if ($file != '.' && $file != '..'){    // Skip if . or ..
     if ($file != '.' &amp;&amp; $file != '..'){    // Skip if . or ..
       $newpath = $dir.'/'.$file;          // Create path. Either dir or file  
       $newpath = $dir.'/'.$file;          // Create path. Either dir or file  


Line 349: Line 350:
//========================================== END Recursive Directory =====
//========================================== END Recursive Directory =====
exit(0);
exit(0);
?>
?&gt;
</pre>
&lt;/pre&gt;
|
|
* '''''Run''''' the batch file (double click on '''Run.bat''')
* '''''Run''''' the batch file (double click on '''Run.bat''')
* '''Result''' Only files with the specified extensions are listed.
* '''Result''' Only files with the specified extensions are listed.
<pre>
&lt;pre&gt;
/(\.txt|\.cnf|\.conf)/
/(\.txt|\.cnf|\.conf)/
</pre>
&lt;/pre&gt;


''Note 1'': The Start folder was moved allowing more folders to be to searched. Outside of the function changed $Array to $File_list_array to avoid confusion.
''Note 1'': The Start folder was moved allowing more folders to be to searched. Outside of the function changed $Array to $File_list_array to avoid confusion.


'''''Note 2'':''' The array is passed to the function using the '''and''' operator '''&'''$Array=false referred to as passing by pointer. It looks a little odd the array name is a pointer, however the array is not created until a value is assigned to it. If its not created it cannot be passed to the function for recursion. What the '''&''' operator does is to create a variable to hold a pointer to the array. This will be created when the function is first called.       
'''''Note 2'':''' The array is passed to the function using the '''and''' operator '''&amp;'''$Array=false referred to as passing by pointer. It looks a little odd the array name is a pointer, however the array is not created until a value is assigned to it. If its not created it cannot be passed to the function for recursion. What the '''&amp;''' operator does is to create a variable to hold a pointer to the array. This will be created when the function is first called.       
   
   
File filtering is performed using preg_match() if a match found save the file to $Array
File filtering is performed using preg_match() if a match found save the file to $Array
<pre>
&lt;pre&gt;
  if (preg_match($f_str, $newpath)){  
  if (preg_match($f_str, $newpath)){  
   $Array[]= $newpath;             
   $Array[]= $newpath;             
  }                                 
  }                                 
</pre>
&lt;/pre&gt;


'''''Complete'':''' Essentially that completes the recursive file search template. You can now add replace code either externally to the function or convert it to perform both search and replace.
'''''Complete'':''' Essentially that completes the recursive file search template. You can now add replace code either externally to the function or convert it to perform both search and replace.
|}
|}
Result of running the above script
Result of running the above script
<pre>
&lt;pre&gt;
./usr/local/apache2/conf/httpd.conf
./usr/local/apache2/conf/httpd.conf
./usr/local/apache2/conf/ssl.conf
./usr/local/apache2/conf/ssl.conf
./usr/local/apache2/LICENSE.txt
./usr/local/apache2/LICENSE.txt
./usr/local/mysql/my.cnf
./usr/local/mysql/my.cnf
</pre>
&lt;/pre&gt;


Press any key to continue . . .
Press any key to continue . . .
Line 386: Line 387:
{|
{|
|-
|-
|'''''test_1.php'''''||&nbsp;
|'''''test_1.php'''''||&amp;nbsp;
|-valign="top"
|-valign=&quot;top&quot;
|
|
<pre>
&lt;pre&gt;
<?php
&lt;?php
$s_str = '/\nListen\s\d+/';              // String to search for
$s_str = '/\nListen\s\d+/';              // String to search for
$r_str = "\nListen 8080";                // Replacement string
$r_str = &quot;\nListen 8080&quot;;                // Replacement string


$sfolder = "./usr/local";                // Start folder
$sfolder = &quot;./usr/local&quot;;                // Start folder
$File_list_array=recur_dir($sfolder);    // Retrieve file list
$File_list_array=recur_dir($sfolder);    // Retrieve file list


Line 411: Line 412:
//=== Recursive Directory ==============================================
//=== Recursive Directory ==============================================
    
    
function recur_dir($dir,&$Array=false){
function recur_dir($dir,&amp;$Array=false){
   $f_str='/(\.txt|\.cnf|\.conf)/';        // Filter, required files
   $f_str='/(\.txt|\.cnf|\.conf)/';        // Filter, required files


Line 417: Line 418:


   while ($file = readdir($dirlist)){      // Iterate through list
   while ($file = readdir($dirlist)){      // Iterate through list
     if ($file != '.' && $file != '..'){    // Skip if . or ..
     if ($file != '.' &amp;&amp; $file != '..'){    // Skip if . or ..
       $newpath = $dir.'/'.$file;          // Create path. Either dir or file  
       $newpath = $dir.'/'.$file;          // Create path. Either dir or file  


Line 436: Line 437:
//========================================== END Recursive Directory =====
//========================================== END Recursive Directory =====
exit(0);
exit(0);
?>
?&gt;
</pre>
&lt;/pre&gt;
|
|
To perform a global search and replace:
To perform a global search and replace:
Line 462: Line 463:
{|
{|
|-
|-
|'''''test_1.php'''''||&nbsp;
|'''''test_1.php'''''||&amp;nbsp;
|-valign="top"
|-valign=&quot;top&quot;
|
|
<pre>
&lt;pre&gt;
<?php
&lt;?php
$start_dir  = './usr/local';            // Start folder
$start_dir  = './usr/local';            // Start folder
$file_type  = '/(\.txt|\.cnf|\.conf)/';  // Filter, required files
$file_type  = '/(\.txt|\.cnf|\.conf)/';  // Filter, required files
$search_str  = '/\nListen\s\d+/';        // String to search for
$search_str  = '/\nListen\s\d+/';        // String to search for
$replace_str = "\nListen 8080";          // Replacement string
$replace_str = &quot;\nListen 8080&quot;;          // Replacement string


if(file_sr_global($start_dir,$file_type,$search_str,$replace_str)){
if(file_sr_global($start_dir,$file_type,$search_str,$replace_str)){
  echo "\n Search and replace complete\n";
  echo &quot;\n Search and replace complete\n&quot;;
}
}


Line 483: Line 484:


   while ($file = readdir($dirlist)){          // Iterate through list
   while ($file = readdir($dirlist)){          // Iterate through list
     if ($file != '.' && $file != '..'){        // Skip if . or ..
     if ($file != '.' &amp;&amp; $file != '..'){        // Skip if . or ..
       $newpath = $start_dir.'/'.$file;        // Create path. Either dir or file  
       $newpath = $start_dir.'/'.$file;        // Create path. Either dir or file  


Line 502: Line 503:
       fwrite($fh, $Data);                    // Write to file
       fwrite($fh, $Data);                    // Write to file
       fclose($fh);                            // close file handle
       fclose($fh);                            // close file handle
       echo $newpath."\n"; //***** Delete this line ***************************
       echo $newpath.&quot;\n&quot;; //***** Delete this line ***************************
       }                                       
       }                                       
       }
       }
Line 513: Line 514:


exit(0);
exit(0);
?>
?&gt;
</pre>
&lt;/pre&gt;
|
|
<br>
&lt;br&gt;
To perform a global search and replace:
To perform a global search and replace:
* Set a folder to start the search from
* Set a folder to start the search from
Line 528: Line 529:
'''$Array[]= $newpath;''' has been replaced there is no feedback hence this test line:
'''$Array[]= $newpath;''' has been replaced there is no feedback hence this test line:


'''echo $newpath."\n";''' displays files that have been searched.
'''echo $newpath.&quot;\n&quot;;''' displays files that have been searched.


After testing it can be removed.
After testing it can be removed.
Line 535: Line 536:
* '''''Run''''' the batch file (double click on '''Run.bat''')
* '''''Run''''' the batch file (double click on '''Run.bat''')
* '''Result''' Since it’s a powerful function I have restricted it to change only the '''Listen''' parameter in Apache’s configuration file. That said it '''still kills''' the server hence re-run script change this line:
* '''Result''' Since it’s a powerful function I have restricted it to change only the '''Listen''' parameter in Apache’s configuration file. That said it '''still kills''' the server hence re-run script change this line:
<pre>
&lt;pre&gt;
$replace_str = "\nListen 8080";
$replace_str = &quot;\nListen 8080&quot;;
</pre>
&lt;/pre&gt;
To:
To:
<pre>
&lt;pre&gt;
$replace_str = "\nListen 80";
$replace_str = &quot;\nListen 80&quot;;
</pre>
&lt;/pre&gt;
Alternatively you can open the file and change it.
Alternatively you can open the file and change it.


Line 553: Line 554:


{|
{|
|-valign="top"
|-valign=&quot;top&quot;
|
|
<pre>
&lt;pre&gt;
//=== Recursive File Search and replace  ==========================================
//=== Recursive File Search and replace  ==========================================
// Inputs:  $start_dir  Absolute or relative path to starting folder. Do not
// Inputs:  $start_dir  Absolute or relative path to starting folder. Do not
Line 562: Line 563:
//                      e.g.  $file_type = '/(\.txt|\.cnf|\.conf)/'  
//                      e.g.  $file_type = '/(\.txt|\.cnf|\.conf)/'  
//          $search_str  A regex patern e.g $search_str  = '/\nListen\s\d+/'
//          $search_str  A regex patern e.g $search_str  = '/\nListen\s\d+/'
//          $replace_str A plain text string e.g. $replace_str = "\nListen 8080"
//          $replace_str A plain text string e.g. $replace_str = &quot;\nListen 8080&quot;
//
//
// Output:  Returns true --- Need to add error checking
// Output:  Returns true --- Need to add error checking
Line 577: Line 578:


   while ($file = readdir($dirlist)){            // Iterate through list
   while ($file = readdir($dirlist)){            // Iterate through list
     if ($file != '.' && $file != '..'){          // Skip if . or ..
     if ($file != '.' &amp;&amp; $file != '..'){          // Skip if . or ..
       $newpath = $start_dir.'/'.$file;          // Create path. Either dir or file  
       $newpath = $start_dir.'/'.$file;          // Create path. Either dir or file  


Line 591: Line 592:
         fclose($fh);                            // Close file handle
         fclose($fh);                            // Close file handle


         $Data = preg_replace($search_str, $replace_str, $Data,-1,$count);// S & R
         $Data = preg_replace($search_str, $replace_str, $Data,-1,$count);// S &amp; R
         if($count){                            // Was a replacement made
         if($count){                            // Was a replacement made
           $fh = fopen($newpath, 'w');          // yes: Open file for write
           $fh = fopen($newpath, 'w');          // yes: Open file for write
           fwrite($fh, $Data);                  // Write new $Data to file
           fwrite($fh, $Data);                  // Write new $Data to file
           fclose($fh);                          // Close file handle
           fclose($fh);                          // Close file handle
           echo $newpath." Replaced ".$count."\n"; //***** Delete this line *******
           echo $newpath.&quot; Replaced &quot;.$count.&quot;\n&quot;; //***** Delete this line *******
         }
         }
       }                                       
       }                                       
Line 607: Line 608:
}                                               
}                                               
//=================================== END Recursive File Search and replace  ======
//=================================== END Recursive File Search and replace  ======
</pre>
&lt;/pre&gt;
|}
|}
OK its true I never practice what I preach.
OK its true I never practice what I preach.
322

edits