PHP CLI: Recursive Search and Replace: Difference between revisions
PHP CLI: Recursive Search and Replace (view source)
Revision as of 17:45, 24 November 2010
, 24 November 2010Reverted edits by Upazixorys (Talk); changed back to last version by Ric
Upazixorys (talk | contribs) No edit summary |
m (Reverted edits by Upazixorys (Talk); changed back to last version by Ric) |
||
Line 1: | Line 1: | ||
{{Uc nav PHP CLI}} | {{Uc nav PHP CLI}} | ||
'''''PHP CLI Recursive Search and Replace''''' | '''''PHP CLI Recursive Search and Replace''''' | ||
Line 14: | Line 13: | ||
|- | |- | ||
| | | | ||
'''''Run.bat'''''||& | '''''Run.bat'''''|| | ||
|-valign= | |-valign="top" | ||
| | | | ||
<pre> | |||
TITLE CLI TEST BAT | TITLE CLI TEST BAT | ||
COLOR B0 | COLOR B0 | ||
Line 26: | Line 25: | ||
echo. | echo. | ||
pause | pause | ||
</pre> | |||
| | | | ||
<br> | |||
Batch file to run test_1.php script | Batch file to run test_1.php script | ||
Line 37: | Line 36: | ||
All scripts on this page will require the above change. | All scripts on this page will require the above change. | ||
|- | |- | ||
|'''''test_1.php'''''||& | |'''''test_1.php'''''|| | ||
|-valign= | |-valign="top" | ||
| | | | ||
<pre> | |||
<?php | |||
$sfolder = | $sfolder = "./usr/local/mysql"; // 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. | echo $line."\n"; | ||
} | } | ||
Line 65: | Line 64: | ||
//========================================== END Recursive Directory ===== | //========================================== END Recursive Directory ===== | ||
exit(0); | exit(0); | ||
? | ?> | ||
</pre> | |||
| | | | ||
* First line sets the initial starting folder in variable '''$sfolder''' | * First line sets the initial starting folder in variable '''$sfolder''' | ||
Line 74: | Line 73: | ||
* 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. | * 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. | ||
* 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 81: | Line 80: | ||
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= | |-valign="top" | ||
| | | | ||
<pre> | |||
./usr/local/mysql/. | ./usr/local/mysql/. | ||
./usr/local/mysql/.. | ./usr/local/mysql/.. | ||
Line 91: | Line 90: | ||
./usr/local/mysql/share | ./usr/local/mysql/share | ||
Press any key to continue . . . | Press any key to continue . . . | ||
</pre> | |||
| | | | ||
<br> | |||
'''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 | 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. | ||
|} | |} | ||
Line 111: | Line 110: | ||
{| | {| | ||
|- | |- | ||
|'''''test_1.php'''''||& | |'''''test_1.php'''''|| | ||
|-valign= | |-valign="top" | ||
| | | | ||
<pre> | |||
<?php | |||
$sfolder = | $sfolder = "./usr/local/mysql"; // 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. | echo $line."\n"; | ||
} | } | ||
//=== Recursive Directory ============================================== | //=== Recursive Directory ============================================== | ||
Line 128: | Line 127: | ||
$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 != '.' & | if ($file != '.' && $file != '..'){ // Skip if . or .. | ||
$newpath = $dir.'/'.$file; // Create path. Either dir or file | $newpath = $dir.'/'.$file; // Create path. Either dir or file | ||
Line 145: | Line 144: | ||
//========================================== END Recursive Directory ===== | //========================================== END Recursive Directory ===== | ||
exit(0); | exit(0); | ||
? | ?> | ||
</pre> | |||
| | | | ||
* 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 155: | Line 154: | ||
* 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> | |||
./udrive/usr/local/mysql/my.cnf | ./udrive/usr/local/mysql/my.cnf | ||
</pre> | |||
'''''Well what a pain''!''' | '''''Well what a pain''!''' | ||
Line 168: | Line 167: | ||
=== Modification === | === Modification === | ||
{| | {| | ||
|-valign= | |-valign="top" | ||
| | | | ||
<pre> | |||
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 | echo "Path = ".$newpath."\n"; | ||
} // for that new folder | } // for that new folder | ||
</pre> | |||
| | | | ||
<br> | |||
Add the '''echo''' line as shown to the above script. | Add the '''echo''' line as shown to the above script. | ||
Line 187: | Line 186: | ||
=== Result === | === Result === | ||
{| | {| | ||
|-valign= | |-valign="top" | ||
| | | | ||
<pre> | |||
Path = ./usr/local/mysql/bin | Path = ./usr/local/mysql/bin | ||
Line 202: | Line 201: | ||
Press any key to continue . . . | Press any key to continue . . . | ||
</pre> | |||
| | | | ||
<br> | |||
An interesting result, it clearly shows recursion is taking place. | An interesting result, it clearly shows recursion is taking place. | ||
Line 229: | Line 228: | ||
{| | {| | ||
|- | |- | ||
|'''''test_1.php'''''||& | |'''''test_1.php'''''|| | ||
|-valign= | |-valign="top" | ||
| | | | ||
<pre> | |||
<?php | |||
$sfolder = | $sfolder = "./usr/local/mysql"; // 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. | echo $line."\n"; | ||
} | } | ||
//=== Recursive Directory ============================================== | //=== Recursive Directory ============================================== | ||
function recur_dir($dir,& | function recur_dir($dir,&$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 != '.' & | if ($file != '.' && $file != '..'){ // Skip if . or .. | ||
$newpath = $dir.'/'.$file; // Create path. Either dir or file | $newpath = $dir.'/'.$file; // Create path. Either dir or file | ||
Line 263: | Line 262: | ||
//========================================== END Recursive Directory ===== | //========================================== END Recursive Directory ===== | ||
exit(0); | exit(0); | ||
? | ?> | ||
</pre> | |||
| | | | ||
<br> | |||
'''''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 276: | Line 275: | ||
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> | |||
function recur_dir($dir,& | function recur_dir($dir,&$Array){ | ||
</pre> | |||
'''To:''' | '''To:''' | ||
<pre> | |||
function recur_dir($dir,& | function recur_dir($dir,&$Array=false){ | ||
</pre> | |||
Initial call to function pass a single parameter. | Initial call to function pass a single parameter. | ||
Line 301: | Line 300: | ||
|- | |- | ||
| | | | ||
<pre> | |||
'/(\.txt|\.cnf|\.conf)/' | '/(\.txt|\.cnf|\.conf)/' | ||
</pre> | |||
| | | | ||
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 312: | Line 311: | ||
{| | {| | ||
|- | |- | ||
|'''''test_1.php'''''||& | |'''''test_1.php'''''|| | ||
|-valign= | |-valign="top" | ||
| | | | ||
<pre> | |||
<?php | |||
$sfolder = | $sfolder = "./usr/local"; // 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. | echo $line."\n"; | ||
} | } | ||
//=== Recursive Directory ============================================== | //=== Recursive Directory ============================================== | ||
function recur_dir($dir,& | function recur_dir($dir,&$Array=false){ | ||
$f_str='/(\.txt|\.cnf|\.conf)/'; // Filter, required files | $f_str='/(\.txt|\.cnf|\.conf)/'; // Filter, required files | ||
Line 331: | Line 330: | ||
while ($file = readdir($dirlist)){ // Iterate through list | while ($file = readdir($dirlist)){ // Iterate through list | ||
if ($file != '.' & | if ($file != '.' && $file != '..'){ // Skip if . or .. | ||
$newpath = $dir.'/'.$file; // Create path. Either dir or file | $newpath = $dir.'/'.$file; // Create path. Either dir or file | ||
Line 350: | Line 349: | ||
//========================================== END Recursive Directory ===== | //========================================== END Recursive Directory ===== | ||
exit(0); | exit(0); | ||
? | ?> | ||
</pre> | |||
| | | | ||
* '''''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> | |||
/(\.txt|\.cnf|\.conf)/ | /(\.txt|\.cnf|\.conf)/ | ||
</pre> | |||
''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 '''& | '''''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. | ||
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> | |||
if (preg_match($f_str, $newpath)){ | if (preg_match($f_str, $newpath)){ | ||
$Array[]= $newpath; | $Array[]= $newpath; | ||
} | } | ||
</pre> | |||
'''''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> | |||
./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> | |||
Press any key to continue . . . | Press any key to continue . . . | ||
Line 387: | Line 386: | ||
{| | {| | ||
|- | |- | ||
|'''''test_1.php'''''||& | |'''''test_1.php'''''|| | ||
|-valign= | |-valign="top" | ||
| | | | ||
<pre> | |||
<?php | |||
$s_str = '/\nListen\s\d+/'; // String to search for | $s_str = '/\nListen\s\d+/'; // String to search for | ||
$r_str = | $r_str = "\nListen 8080"; // Replacement string | ||
$sfolder = | $sfolder = "./usr/local"; // Start folder | ||
$File_list_array=recur_dir($sfolder); // Retrieve file list | $File_list_array=recur_dir($sfolder); // Retrieve file list | ||
Line 412: | Line 411: | ||
//=== Recursive Directory ============================================== | //=== Recursive Directory ============================================== | ||
function recur_dir($dir,& | function recur_dir($dir,&$Array=false){ | ||
$f_str='/(\.txt|\.cnf|\.conf)/'; // Filter, required files | $f_str='/(\.txt|\.cnf|\.conf)/'; // Filter, required files | ||
Line 418: | Line 417: | ||
while ($file = readdir($dirlist)){ // Iterate through list | while ($file = readdir($dirlist)){ // Iterate through list | ||
if ($file != '.' & | if ($file != '.' && $file != '..'){ // Skip if . or .. | ||
$newpath = $dir.'/'.$file; // Create path. Either dir or file | $newpath = $dir.'/'.$file; // Create path. Either dir or file | ||
Line 437: | Line 436: | ||
//========================================== END Recursive Directory ===== | //========================================== END Recursive Directory ===== | ||
exit(0); | exit(0); | ||
? | ?> | ||
</pre> | |||
| | | | ||
To perform a global search and replace: | To perform a global search and replace: | ||
Line 463: | Line 462: | ||
{| | {| | ||
|- | |- | ||
|'''''test_1.php'''''||& | |'''''test_1.php'''''|| | ||
|-valign= | |-valign="top" | ||
| | | | ||
<pre> | |||
<?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 = | $replace_str = "\nListen 8080"; // 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 | echo "\n Search and replace complete\n"; | ||
} | } | ||
Line 484: | Line 483: | ||
while ($file = readdir($dirlist)){ // Iterate through list | while ($file = readdir($dirlist)){ // Iterate through list | ||
if ($file != '.' & | if ($file != '.' && $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 503: | Line 502: | ||
fwrite($fh, $Data); // Write to file | fwrite($fh, $Data); // Write to file | ||
fclose($fh); // close file handle | fclose($fh); // close file handle | ||
echo $newpath. | echo $newpath."\n"; //***** Delete this line *************************** | ||
} | } | ||
} | } | ||
Line 514: | Line 513: | ||
exit(0); | exit(0); | ||
? | ?> | ||
</pre> | |||
| | | | ||
<br> | |||
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 529: | Line 528: | ||
'''$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. | '''echo $newpath."\n";''' displays files that have been searched. | ||
After testing it can be removed. | After testing it can be removed. | ||
Line 536: | Line 535: | ||
* '''''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> | |||
$replace_str = | $replace_str = "\nListen 8080"; | ||
</pre> | |||
To: | To: | ||
<pre> | |||
$replace_str = | $replace_str = "\nListen 80"; | ||
</pre> | |||
Alternatively you can open the file and change it. | Alternatively you can open the file and change it. | ||
Line 554: | Line 553: | ||
{| | {| | ||
|-valign= | |-valign="top" | ||
| | | | ||
<pre> | |||
//=== 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 563: | Line 562: | ||
// 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 = | // $replace_str A plain text string e.g. $replace_str = "\nListen 8080" | ||
// | // | ||
// Output: Returns true --- Need to add error checking | // Output: Returns true --- Need to add error checking | ||
Line 578: | Line 577: | ||
while ($file = readdir($dirlist)){ // Iterate through list | while ($file = readdir($dirlist)){ // Iterate through list | ||
if ($file != '.' & | if ($file != '.' && $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 592: | Line 591: | ||
fclose($fh); // Close file handle | fclose($fh); // Close file handle | ||
$Data = preg_replace($search_str, $replace_str, $Data,-1,$count);// S & | $Data = preg_replace($search_str, $replace_str, $Data,-1,$count);// S & 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. | echo $newpath." Replaced ".$count."\n"; //***** Delete this line ******* | ||
} | } | ||
} | } | ||
Line 608: | Line 607: | ||
} | } | ||
//=================================== END Recursive File Search and replace ====== | //=================================== END Recursive File Search and replace ====== | ||
</pre> | |||
|} | |} | ||
OK its true I never practice what I preach. | OK its true I never practice what I preach. |