2014-07-08 20 views
10

Also im Grunde möchte ich ein paar CSV-Dateien zusammenführen. Im mit dem folgende Skript, das zu tun:Zusammenführen von CSV-Dateien: Anhängen statt Zusammenführen

paste -d , *.csv > final.txt 

jedoch das für mich in der Vergangenheit gearbeitet hat, aber dieses Mal ist es nicht funktioniert. Es hängt die Daten aneinander an, im Gegensatz zu einander. Zum Beispiel zwei Dateien, die Datensätze in folgendem Format enthalten

CreatedAt ID 
Mon Jul 07 20:43:47 +0000 2014 4.86249E+17 
Mon Jul 07 19:58:29 +0000 2014 4.86238E+17 
Mon Jul 07 19:42:33 +0000 2014 4.86234E+17 

Wenn merged geben

CreatedAt ID CreatedAt ID 
Mon Jul 07 20:43:47 +0000 2014 4.86249E+17 Mon Jul 07 18:25:53 +0000 2014 4.86215E+17 
Mon Jul 07 19:58:29 +0000 2014 4.86238E+17 Mon Jul 07 17:19:18 +0000 2014 4.86198E+17 
Mon Jul 07 19:42:33 +0000 2014 4.86234E+17 Mon Jul 07 15:45:13 +0000 2014 4.86174E+17 
              Mon Jul 07 15:34:13 +0000 2014 4.86176E+17 

Würde jemand wissen, was der Grund dafür ist? Oder was kann ich tun, um das Zusammenführen unter Datensätze zu erzwingen?

+0

es wie eine Ihrer CSV-Datei scheint Anzahl der Linien hat, die andere CSV-Datei. Nicht sicher, woher du den Platz bekommst. Der Befehl paste verwendet ",", um die Einträge zu trennen. –

+1

Meinst du, du hättest 'cat file * .csv> final.csv'.Das würde dir Aufzeichnungen "unter einander" geben. Viel Glück. – shellter

+0

Was ist der Zweck von -d, '? – Cyrus

Antwort

25

Unter der Annahme, dass alle CSV-Dateien das gleiche Format haben und alle beginnen mit dem gleichen Header, Sie ein kleines Skript schreiben können, wie die folgenden zu append alle Dateien in nur eine und nur einmal den Kopf zu nehmen.

#!/bin/bash 
OutFileName="X.csv"      # Fix the output name 
i=0          # Reset a counter 
for filename in ./*.csv; do 
if [ "$filename" != "$OutFileName" ] ;  # Avoid recursion 
then 
    if [[ $i -eq 0 ]] ; then 
     head -1 $filename > $OutFileName # Copy header if it is the first file 
    fi 
    tail -n +2 $filename >> $OutFileName # Append from the 2nd line each file 
    i=$(($i + 1))      # Increase the counter 
fi 
done 

Anmerkungen:

  • Der head -1 oder head -n 1 Befehl Drucken der ersten Zeile der Datei (der Kopf).
  • Der tail -n +2 druckt der Schwanz einer Datei aus den Linien der Startnummer 2 (+2)
  • -Test [ ... ] verwendet wird, um die Ausgabedatei von der Eingabeliste auszuschließen.
  • Die Ausgabedatei wird jedes Mal neu geschrieben.
  • Der Befehl cat a.csv b.csv > X.csv kann einfach verwendet werden, um a.csv und b csv in einer einzigen Datei anzuhängen (aber Sie kopieren 2 mal die Kopfzeile).

Der paste Befehl fügt die Dateien auf einer Seite des anderen. Wenn eine Datei Leerstellen als Zeilen enthält, können Sie die Ausgabe erhalten, die Sie oben gemeldet haben.
Die Verwendung von -d , fragt nach paste command, um Felder zu definieren, die durch ein Komma getrennt sind ,, aber dies ist nicht der Fall für das Format der Dateien, die Sie oben gemeldet haben.

Der Befehl cat verkettet stattdessen Dateien und druckt auf der Standardausgabe, dh er schreibt eine Datei nach der anderen.

Siehe man head oder man tail für die Syntax der einzelnen Optionen (einige Version head -1 andere statt head -n 1 erlaubt) ...

+0

Dies funktionierte perfekt. Danke. – user2233834

+0

Ich lese jetzt, was er meinte. Btw, Sie können dieses Inkrement auf "i" Variable innerhalb IF-Anweisung statt innerhalb der Schleife setzen. –

+0

@ArunSangal Es ist richtig. Mein Fehler, ich habe eine alte Version kopiert. Wenn das Inkrement außerhalb des "if" -Blocks liegt und die Ausgabedatei die erste der Liste ist, wird die Kopfzeile nie in der Ausgabedatei enthalten sein. – Hastur

0

Sie so viel @wahwahwah Dank. benutzte ich das Skript nautilus-Aktion zu machen, aber es korrekt funktionieren nur, damit ändert sich:

#!/bin/bash 

for last; do true; done 

OutFileName=$last/RESULT_`date +"%d-%m-%Y"`.csv      # Fix the output name 

i=0          # Reset a counter 
for filename in "$last/"*".csv"; do 

if [ "$filename" != "$OutFileName" ] ;  # Avoid recursion 
then 
    if [[ $i -eq 0 ]] ; then 
     head -1 "$filename" > "$OutFileName" # Copy header if it is the first file 
    fi 
    tail -n +2 "$filename" >> "$OutFileName" # Append from the 2nd line each file 
    i=$(($i + 1))      # Increase the counter 
fi 
done