I have a script which goes through every filename in a directory and removes unwanted files. Amount other things, it matches filenames in a CSV file and then removes a file in an adjacent cell.
<?php
$gameList = trim(shell_exec("ls -a -1 -I . -I .. -I Removed"));
$gameArray = explode("\n", $gameList);
shell_exec('mkdir -p Removed');
echo "\033[01;32m\n\n<<<<<<<<<<Starting Scan>>>>>>>>>>\n\n";
// Do the magic for every file
foreach ($gameArray as $thisGame)
{
// Ensure continue if already removed
if (!$thisGame) continue;
if (!file_exists($thisGame)) continue;
// Manipulate names to look and play nice
$niceName = trim(preg_replace('%[\(|\[].*%', '', $thisGame));
$thisGameNoExtension = preg_replace('/\.' . preg_quote(pathinfo($thisGame, PATHINFO_EXTENSION) , '/') . '$/', '', $thisGame);
// Let the user know what game is being evaluated
echo "\033[00;35m{$thisGameNoExtension} ... ";
$f = fopen("ManualRegionDupes.csv", "r");
while ($row = fgetcsv($f))
{
if ($row[1] == $thisGameNoExtension)
{
$primaryFile = $row[0];
$ext = pathinfo($thisGame, PATHINFO_EXTENSION);
$fCheck = trim(shell_exec("ls -1 " . escapeshellarg($primaryFile) . "." . escapeshellarg($ext) . " 2>/dev/null"));
if ($fCheck)
{
echo "ECHO LION";
shell_exec("mv " . escapeshellarg($thisGame) . " Removed/");
continue;
}
else
{
echo "ECHO ZEBRA";
continue;
}
break;
}
}
fclose($f);
echo "Scanned and kept";
}
echo "\033[01;32m\n<<<<<<<<<<Process Complete>>>>>>>>>>\n\n";
?>
It's working, however I don't understand why I am seeing the final echo "Scanned and Kept" straight after either "ECHO ZEBRA" or "ECHO LION" - as I have "continue" calls straight after them, which should restart the loop and move on to the next file. I'm sure I just need to re-jig something somewhere, but I've been fiddling for hours and I'm completely stumped. I'd be super greatful for any help! Many thanks!
The continue is just working for the inner loop which is reading the individual lines. If you want to skip to the end of the outer loop, you will need to use...
continue 2;
This allows you to say continue for 2 levels of loop.
You have nothing but a break after your continue calls, what else would it run? Edit, if you want the continue on the outer loop, move it there. The continue is just in the wrong loop.
Related
I am running a python script inside my PHP file to do some analysis. After, "fgets" is used to extract the output and store the extraction in a string variable.
What I am trying to do:
-I have an echo statement in my PHP file that outputs a button called "Full analysis." When a user clicks on that button, I want to open up a new page on a new tab and the new page will contain the output stored on the string variable.
Is this possible? I've tried searching around and not getting much luck. Could you guys point me in the right direction? Thank you.
Edit:
Code to run python script:
$output= popen("python param1 param2 " 2>&1", "r");
if ($output) {
while (($line = fgets($output)) !== false) {
#echo $line;
$str_var .= $line . '<br>';
}
if ($str_var == ""){
$str_var = "ERR: ";
}
}else{
$analysis_output = "Cannot run $str_var ";
}
fclose($output);
}
PHP code to out a button using HTML:
echo "<pre><a target='_blank' href='http://" . param . "'>" . "<button>" . "More info" . "</button>" ."<a/>\n";
I wrote the code as follows:
<?php
array_shift($argv);
$taskid=$argv[0];
$file1=file_get_contents($argv[1]);
$file2=fopen($argv[2],"w");
echo $taskid."\n".$file1."\n".$file2."\n";
?>
I execute this program as php myfile.php 1 1.txt 2.txt
Where 1 is the taskid, 1.txt is the input file and 2.txt is the output file.
I want to modify this program in such a way that it runs even though I don't pass any arguments that is like php myfile.php should run. I want to place an if condition for that. I worked with the conditions like if(*argv<=1) and if(argc==NULL) etc., but none of them are working.
I need a perfect condition that checks if no arguments are passed then my program should show a user friendly message.
Can someone help me??
if ($argc !== 4) {
// show message
Try this:
<?php
array_shift($argv);
if (empty($argv) || count($argv) != 3) {
echo "Incorrect number of arguments\n";
}
else {
$taskid = $argv[0];
$file1 = file_get_contents($argv[1]);
$file2 = fopen($argv[2],"w");
echo $taskid . "\n" . $file1 . "\n" . $file2 . "\n";
}
Strange issue i'm having. when I perform a file check with File_exist or is_file it only checks half the files... what my script does is processes a csv file and inserts the data into the table only if the file exist on the server. if I remove the file check everything processes fine. I've double check to make sure all files exist on the server it just stop half way through for some reason.
$column_headers = array();
$row_count = 0;
if (mysql_result(
mysql_query(
"SELECT count(*) FROM load_test WHERE batch_id='".$batchid."'"
), 0
) > 0) {
die("Error batch already present");
}
while (($data = fgetcsv($handle, 0, ",")) !== FALSE) {
if ($row_count==0){
$column_headers = $data;
} else {
$dirchk1 = "/temp/files/" . $batchid . "/" .$data[0] . ".wav";
$dirchk2 = "/files/" . $batchid . "/" . $data[1] . ".wav";
if (file_exists($dirchk1)) {
$importword="INSERT into load_test SET
word = '".$data[2]."',
batch_id = UCASE('".$batchid."'),
accent = '".$data[15]."'
";
mysql_query($importword);
$word_id = mysql_insert_id();
echo $word_id . "\n";
}
}
++$row_count;
}
Try it using "-e" test condition.
For eg ::
if(-e $dirchk1){
print "File exists\n";
}
Also make sure if your variable $dirchk1 etc are getting correctly populated or not.
Please check if it works or not.
the script processed correctly, human error whey verifying on my part.
This below goes through files in a directory, reads them and saves them in files of 500 lines max to a new directory.
This works great for me (thanks Daniel) but, I need a modification.
I would like to save to alpha num based files.
First, sort the array alpha numerically (already lowercase) would be the first step I assume.
Grab all of the lines in each $incoming."/.txt" that start with "a" and put them into a folder at $save500."/a" but, a max of 500 lines each.
(I guess it would be best to start with the first at the top of the sort so "0" not "a" right?)
All the lines that start with a number, go into $save500."/num".
None of the lines will start with anything but a-z0-9.
This will allow me to search my files for a match more efficiently using this flatfile method. Narrowing it down to one folder.
$nextfile=0;
if (glob("" . $incoming . "/*.txt") != false){
$nextfile = count(glob("" . $save500 . "/*.txt"));
$nextfile++;
}
else{$nextfile = 1;}
/**/
$files = glob($incoming."/*.txt");
$lines = array();
foreach($files as $file){
$lines = array_merge($lines, file($file, FILE_SKIP_EMPTY_LINES | FILE_IGNORE_NEW_LINES));
}
$lines = array_unique($lines);
/*this would put them all in one file*/
/*file_put_contents($dirname."/done/allofthem.txt", implode("\n", $lines));*/
/*this breaks them into files of 500*/
foreach (array_chunk($lines, 500) as $chunk){
file_put_contents($save500 . "/" . $nextfile . ".txt", implode("\n", $chunk));
$nextfile++;
}
Each still need to be in a max of 500 lines.
I will graduate to mysql later on. Only been doing this a couple months now.
As if that is not enough. I even thought of taking the first two characters off. Making directories with subs a/0 thru z/z!
Could be the wrong approach above since no responses.
But I want a word like aardvark saved to the 1.txt the a/a folder (appending). Unless 1.txt has 500 lines then save it to a/a 2.txt.
So xenia would be appended to the x/e folder 1.txt file unless there are 500 lines so create 2.txt and save it there.
I will then be able to search for those words more efficiently without loading a ton into memory or looping through files /lines that won't contain a match.
Thanks everyone!
I wrote some code here that should do what you're looking for, it's not a perfomance beauty but should do the job. Try it in a safe environment, no guarantee for any data-loss ;)
Comment if there are any errors, it's pretty late here ;) I have to get some sleep ;)
NOTE: This one only works if every line has at least 2 characters! ;)
$nextfile=0;
if (glob("" . $incoming . "/*.txt") != false){
$nextfile = count(glob("" . $save500 . "/*.txt"));
$nextfile++;
}
else
{
$nextfile = 1;
}
$files = glob($incoming."/*.txt");
$lines = array();
foreach($files as $file){
$lines = array_merge($lines, file($file, FILE_SKIP_EMPTY_LINES | FILE_IGNORE_NEW_LINES));
}
$lines = array_unique($lines);
/*this would put them all in one file*/
/*file_put_contents($dirname."/done/allofthem.txt", implode("\n", $lines));*/
/*this breaks them into files of 500*/
// sort array
sort($lines);
// outer grouping
$groups = groupArray($lines, 0);
$group_keys = array_keys($groups);
foreach($group_keys as $cKey) {
// inner grouping
$groups[$cKey] = groupArray($groups[$cKey], 1);
foreach($groups[$cKey] as $innerKey => $innerArray) {
$nextfile = 1;
foreach(array_chunk($innerArray, 500) as $chunk) {
file_put_contents($save500 . "/" . $cKey . "/" . $innerKey . "/" . $nextfile . ".txt", implode("\n", $chunk));
$nextfile++;
}
}
}
function groupArray($data, $offset) {
$grouped = array();
foreach($data as $cLine) {
$key = substr($cLine, $offset, 1);
if(!isset($grouped[$key])) {
$grouped[$key] = array($cLine);
}
else
{
$grouped[$key][] = $cLine;
}
}
return $grouped;
}
$allfiles = glob($searchdir."*.txt");
$elist = array();
foreach($allfiles as $file){
$lines = array_merge($elist, file($file, FILE_SKIP_EMPTY_LINES | FILE_IGNORE_NEW_LINES));
}
foreach ($lines as $existing){
// this echos a number // echo "<br />Existing".$existing."<br />";
if (preg_match("/\b".$searchforthis."\b/i", $existing)) {
echo "A match was found.";
continue;
} else {
echo "A match was not found.";
$nodupe ="y";
continue;
}
}
In the above I am attempting to check for a match in a directory of files and return a true or false for the next step.
It is obviously not working. I echoed the line in attempt to troubleshoot but, I get a number not the word on the line.
The file(s) being searched single column of words with only 100 lines each. There may be up to 5 of them in the directory.
I echoed the paths and other vars and all is correct. In just never finds a match.
I know I should learn mysql but, I need this to work.
I am also unsure about the continue or break. This routine resides in a for loop inside an if.
I want this to stop looking when a match was found.
Thanks for any guidance.
I added the file write part here in case I messed that up causing the problem. It writes a number to the file and does not append even when I bypass the append switch below and null the statement that does not..
/****Write the entry if no match******/
if ($nodupe != "y"){
if($append == "n"){
$name .= $searchforthis."\n";
file_put_contents($filepath.$writefile.".txt", $name, LOCK_EX);
}
else{
file_put_contents($filepath.$writefile.".txt", $name, FILE_APPEND | LOCK_EX);
}
}
Try this:
<?php
# variables
$sDir = __DIR__; # php 5.3, for php <5.3 use dirname(__FILE__);
$sFilePattern = '*.php';
$sSearch = 'printf';
# config
$sRegExp = '/\b'.$sSearch.'\b/i';
# code
foreach (glob($sDir . DIRECTORY_SEPARATOR . $sFilePattern) as $sFile){
foreach (file($sFile) as $nLineNumber => $sLine){
if (preg_match($sRegExp, $sLine) == 1){
printf('<br/>Word "%s" found in %s, line %d', $sSearch, $sFile, $nLineNumber);
} // if
} // foreach
} // foreach
It's literally the same thing that yours. Should show 2 occurences of 'printf'.
The /m modifier will search across lines, so you don't need to scan each line individually:
$search = 'whatever';
foreach (glob($dir . '/*.txt') as $file) {
if (preg_match('/^' . $search . '$/m', file_get_contents($file))) {
echo "$file contains $search\n";
break;
} else {
echo "$file does not contain $search\n";
}
}
Alternatively, if your word lists don't change very much, you'll be better off just making them into PHP arrays and include()'ing them straight into your script:
$list = array(
'word1',
'word2',
'word3',
// ...
);
And then you can just use in_array() to scan for the word.