Eu tive uma necessidade semelhante, concatenando um grande número de arquivos com nomes semelhantes. Eu peguei uma pequena ferramenta de linha de comando em C #:
class Program
{
static int Main(string[] args)
{
if (args.Length < 3)
{
Console.WriteLine("Expected three to four arguments: the input folder; the input pattern; the output file name; and (optionally) the number of header rows to skip in subsequent files.");
return -1;
}
string inputFolder = args[0];
string inputPattern = args[1];
string outputFile = args[2];
int headerRows = args.Length == 4 ? Int32.Parse(args[3]) : 0;
// Clean up inputs
if (inputFolder.StartsWith("\"") && inputFolder.EndsWith("\"")) inputFolder = inputFolder.Substring(1, inputFolder.Length - 2);
if (inputFolder.EndsWith("\") == false) inputFolder = inputFolder + '\';
if (Path.IsPathRooted(outputFile) == false) outputFile = inputFolder + outputFile;
Console.WriteLine("Reading \"{0}\" from \"{1}\" to \"{2}\".", inputPattern, inputFolder, outputFile);
// Merge the files
int records = 0;
using (StreamWriter collectedFile = CreateCollectedFile(outputFile))
{
foreach (string filePath in Directory.GetFiles(inputFolder, inputPattern))
{
if (filePath == outputFile) continue;
Console.Write("Reading \"{0}\"...", filePath);
// Note that we do not want to skip headers in the first file, as we want the final file to include *1* copy of the header
int recordsThisFile = AppendFile(filePath, collectedFile, records == 0 ? 0 : headerRows);
Console.WriteLine("copied {0} records.", recordsThisFile.ToString("#,##0"));
records += recordsThisFile;
}
}
Console.WriteLine("Read {0} records.", records.ToString("#,##0"));
return 0;
}
private static StreamWriter CreateCollectedFile(string path)
{
if (File.Exists(path)) File.Delete(path);
return new StreamWriter(path);
}
private static int AppendFile(string from, StreamWriter to, int headerRows)
{
int records = 0;
using (StreamReader reader = new StreamReader(File.OpenRead(from)))
{
string line;
while (reader.EndOfStream == false)
{
line = reader.ReadLine();
if (++records > headerRows) to.WriteLine(line);
}
}
return records;
}
}
Uso:
MergeFiles . ab???.csv Questions.csv 0
MergeFiles . ab????.csv Choices.csv 0
Observe o primeiro parâmetro, .
, indicando o diretório atual.
Se você tiver um compilador C # à mão, isso será feito. Eu colocaria o binário, mas se você for propriamente paranóico, não gostaria de executar tal coisa de qualquer maneira.
Como Faucett aponta, o * NIX já tem bons utilitários para isso. Se você está no Windows, isso pode ajudar.