Reputation: 7037
Description:
I have a directory that contains a large number of files named as follows:
2013_11_weekly.csv
2013_10_weekly.csv
2013_08_weekly.csv
2013_09_weekly.csv
2013_11_any_string.csv
2013_10_any_string.csv
Problem:
How can I iterate over the directory and merge all the files that end with the same string into single files?
The end result would be a directory containing the following files.
weekly.csv
any_string.csv
...
Research:
I have the following code snippet that merges all all files.
<?php
$files = glob("*.csv");
$out = fopen("merged_files.csv", "w");
foreach($files as $file){
fwrite($out, file_get_contents($file));
}
fclose($out);
echo "files merged";
?>
How can I amend my script to achieve the above?
I know I may have to use an array function, a str_
function and possibly a regular expression function.
Upvotes: 2
Views: 2110
Reputation: 2668
Try this - it assumes the rules to grouping files (2013_[two-digits]_[grouping_string]). Nice trick is using ?P sign in regexp, which will put the aggregation string into $maches array under 'string_aggr' key:
$filenameRegexp = '/2013_[0-9]{2}_(?P<string_aggr>.+)\.csv/';
foreach (glob('*.csv') as $filename) {
if (preg_match($filenameRegexp, $filename, $matches)) {
$aggrFilename = $matches['string_aggr'] '.csv';
file_put_contents($aggrFilename, file_get_contents(filename), FILE_APPEND);
}
}
What it does is basically:
After running it you should get desired results - multiple files with aggregated contents, according to those "anything" parts, in your case: weekly, any_string etc.
Upvotes: 2
Reputation: 1239
Instead of fwrite, you should use file_put_content. This function is able to append data to a file.
Description
int file_put_contents ( string $filename , mixed $data [, int $flags = 0 [, resource $context ]] )
This function is identical to calling fopen(), fwrite() and fclose() successively to write data to a file.
If filename does not exist, the file is created. Otherwise, the existing file is overwritten, unless the FILE_APPEND flag is set.
resulting in code like (not tested, just for understanding):
<?php
$files = glob("*.csv");
foreach($files as $file){
// get substring 6 chars before the last 4 chars (.csv)
$type = substr($file, -4, -10)
// switch based on the substring $type
switch($type) {
case "weekly":
file_put_content("merged_files_weekly.csv", file_get_contents($file), FILE_APPEND);
break;
case "string" :
file_put_content("merged_any_string.csv", file_get_contents($file), FILE_APPEND);
break;
default:
// do nothing
break;
}
}
echo "files merged";
Upvotes: 0
Reputation: 3890
You can do an array, concatenate all values into array and then create those files
For example :
$files = glob("*.csv");
$files_content = array();
//parse all your files
foreach($files as $file){
//get the suffix (ie '_weekly')
$filename_end = substr(basename($file), 8);
if(!isset($files_content[$file])) $files_content[$file] = "";
//concatenate strings
$files_content[$file] .= file_get_contents($file);
}
//and then create those files
foreach($fields_content as $filename => $content){
$out = fopen($filename, "w");
fwrite($out, $content);
fclose($out);
}
Upvotes: 0
Reputation: 43552
This is very simple, you must just figure out, how to fetch common name from filenames.
In my example, I split filename on 8th position (2013_11_weekly.csv
becomes weekly.csv
):
$files = glob("*.csv");
$out = array();
foreach($files as $file) {
$name = substr(basename($file), 8);
if (!isset($out[$name])) {
$out[$name] = fopen($name, "w");
}
fwrite($out[$name], file_get_contents($file));
}
foreach ($out as $f) {
fclose($f);
}
Upvotes: 1
Reputation: 134
It may be helpful for you. If you not getting your proper answer than let me know. merging multiple csv files using php
Upvotes: 0