ubuntuusers.de

Wie kann man Textdateien zeilenweise vergleichen?

Status: Gelöst | Ubuntu-Version: Kubuntu 8.04 (Hardy Heron)
Antworten |

technohead

Avatar von technohead

Anmeldungsdatum:
1. April 2007

Beiträge: 869

Hallo,
hatte gestern ein wenig Pech mit der Installation des Gnome-Desktop und würde die Installation gerne Rückgängig machen. Nun habe ich einige Paketlisten welche bei jedem Backup automatisch angelegt werden und eine von Heute, welche ich gerne mit der vom letzten Freitag vergleichen würde um die Differenz zu deinstallieren.

Allerdings habe ich keine Ahnung wie man Dateien zeilenweise vergleicht und das Ergebnis bzw. die Differenz in eine neue Datei schreibt.

vielen Dank schon mal

rocco_storm Team-Icon

Avatar von rocco_storm

Anmeldungsdatum:
3. November 2005

Beiträge: 1811

Wohnort: Ruhrpott

Moin,

man diff

oliver1804

Anmeldungsdatum:
27. März 2006

Beiträge: 279

Wohnort: Elmshorn

am einfachsten und schnellsten scheint mir allerdings:

comm --help

Ist sicherlich nicht so mächtig wie diff dafür aber übersichtlich in der Bedienung

technohead

(Themenstarter)
Avatar von technohead

Anmeldungsdatum:
1. April 2007

Beiträge: 869

Herzlichen Dank für die Tips - habe es mit diff hinbekommen

diff /mnt/backup/Paketlisten/neu.list /mnt/backup/Paketlisten/alt.list > /mnt/backup/Paketlisten/differenz.list        

Dann habe ich die Ausgabe von Hand (ca 400 Zeilen) nachbearbeitet, so dass ich eine In- als auch Deinstallations-Liste bekommen habe - dann weiter mit:

xargs -a "/mnt/backup/Paketlisten/deinstall.list" sudo apt-get remove --purge
xargs -a "/mnt/backup/Paketlisten/install.list" sudo apt-get install
sudo apt-get clean

So weit so gut - allerdings frage ich mich ob es irgendwie möglich wäre, die Ausgabe von diff mit einem Schell-Script automatisch auf zwei Dateien zu verteilen. So dass in der einen Datei nur Paket-Namen stehen welche nur in der alten Liste vorhanden sind, und umgekehrt...

BadBoy

Avatar von BadBoy

Anmeldungsdatum:
25. Oktober 2007

Beiträge: 479

öh...das hängt nun davon ab, wie die Dateien aussehen? mach doch mal Beispieldateien für neu.list und alt.list (je so ca. 5 Zeilen oder wieviele nötig sind, um das Problem am kürzesten zu beschreiben)

technohead

(Themenstarter)
Avatar von technohead

Anmeldungsdatum:
1. April 2007

Beiträge: 869

Paketliste (alt)

akregator
amarok
amarok-engines
amarok-xine


Paketliste (neu)

akregator
alsa-base
alsa-oss
alsa-utils
kdegames
kdegames-card-data
kdegraphics-kfile-plugins
kdelibs-data
kdelibs4c2a
kdemultimedia-kfile-plugins
kdemultimedia-kio-plugins

Die Original-Dateien sind wesentlich länger (ca 1200 Zeilen) - Ich verwende ein modifiziertes Backup-Script welches bei jedem Backup auch eine Liste mit den jeweils installierten Paketen erstellt. Die Ausgabe der Differenzen sieht dann wenn man diff verwendet in etwa so aus:

user@k-office:~$ diff /mnt/backup/Paketlisten/liste.alt /mnt/backup/Paketlisten/liste.neu
2,4c2,11
< amarok
< amarok-engines
< amarok-xine
---
> alsa-base
> alsa-oss
> alsa-utils
> kdegames
> kdegames-card-data
> kdegraphics-kfile-plugins
> kdelibs-data
> kdelibs4c2a
> kdemultimedia-kfile-plugins
> kdemultimedia-kio-plugins
user@k-office:~$

Die geschlossenen spitzen Klammern zeigen an, dass diese Zeile in der zweiten Datei hinzugefügt wurde. Man müsste also zunächst die Zeilen anhand der spitzen Klammern auf zwei Text-Dateien verteilen, wobei Zeilen mit Kommata oder drei aufeinander folgenden Bindestrichen ausgelassen werden müssten.

BadBoy

Avatar von BadBoy

Anmeldungsdatum:
25. Oktober 2007

Beiträge: 479

dann greppe die zeilen halt da raus:

grep "^<"

bzw.

grep "^>"

und dann einfach mittels awk oder sed den passenden Teil rausschneiden

...| sed 's/^. //' 
# oder
... | awk {print $2}

technohead

(Themenstarter)
Avatar von technohead

Anmeldungsdatum:
1. April 2007

Beiträge: 869

Danke, grep und sed brachten mich auf den richtigen Weg:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
#!/usr/bin/bash
# dieses Script kann das System in Bezug auf die Installierten Pakete auf einen früheren Stand zuücksetzen
listpath="/mnt/Backup/backup/Paketlisten" # Pfad zu den Paketlisten
alte_liste="2009-02.11-19.13.list" # gewünschter Installations-Zustand
neue_liste="2009-02.12-14.47.list" # aktuelle Paketliste
cd $listpath
diff $listpath/$alte_liste $listpath/$neue_liste > $listpath/differenz.list
grep "^>" $listpath/differenz.list > $listpath/alt.list
sed -e 's/^>\ //g' $listpath/alt.list > $listpath/instalieren.list
grep "^<" $listpath/differenz.list > $listpath/neu.list
sed -e 's/^<\ //g' $listpath/neu.list > $listpath/deinstalieren.list
rm differenz.list
rm alt.list
rm neu.list
# Bitte entferne die folgenden Rauten nur wenn Du sicher bist was du tust
# xargs -a "$listpath/deinstalieren.list" sudo apt-get remove --purge
# xargs -a "$listpath/instalieren.list" sudo apt-get install
# sudo apt-get clean

Noch eine Frage:
kann man irgendwie Parameter (z.B. die Dateinamen der Paketlisten) an das shellscript übergeben?

e1bart0 Team-Icon

Avatar von e1bart0

Anmeldungsdatum:
12. Mai 2007

Beiträge: 927

Wohnort: München

Die Aufrufparameter stehen in $1, $2, ... bzw. in $@.

technohead

(Themenstarter)
Avatar von technohead

Anmeldungsdatum:
1. April 2007

Beiträge: 869

Jetzt ist ich mein Script fertig. Es vergleicht eine zu einem früheren Zeitpunkt angelegte Paket-Liste mit den aktuell installierten Paketen - anschließend werden die Unterschiede analysiert und auf eine Installationsliste als auch eine Deinstallationsliste verteilt. Diese Differenzlisten werden genutzt um das System in Bezug auf die installierten Pakete zurückzusetzen. Wenn es jemand gebrauchen kann:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#!/usr/bin/bash
# dieses Script kann das System in Bezug auf die Installierten Pakete auf einen früheren Stand zuücksetzen
listpath="/mnt/backup/Paketlisten" # Pfad zu den Paketlisten
alte_liste=$1;
hilfetext="Unzureichende Argumente!\nBitte geben Sie als Parameter eine Wiederherstellungs-Liste an"
cd $listpath
if [ "$alte_liste" = "" ]
then
  echo $hilfetext;
  ls
  exit 1;
fi
aktuell=`/bin/date +20%y-%m.%d-%H.%M`
typ=".list";
dpkg --get-selections | awk '!/deinstall|purge|hold/ {print $1}' > $listpath/$aktuell$typ;
diff $listpath/$alte_liste $listpath/$aktuell$typ > $listpath/differenz$typ;
grep "^<" $listpath/differenz$typ > $listpath/alt$typ;
sed -e 's/^<\ //g' $listpath/alt$typ > $listpath/instalieren$typ;
grep "^>" $listpath/differenz$typ > $listpath/neu$typ;
sed -e 's/^>\ //g' $listpath/neu$typ > $listpath/deinstalieren$typ;
rm differenz$typ;
rm alt$typ;
rm neu$typ;
# Bitte entferne die folgenden Rauten nur wenn Du sicher bist, was du tust
# xargs -a "$listpath/deinstalieren$typ" sudo apt-get remove --purge
# xargs -a "$listpath/instalieren$typ" sudo apt-get install
# sudo apt-get clean
# rm deinstalieren$typ;
# rm instalieren$typ;
# cp $aktuell$typ $aktuell.bac;
# rm $aktuell$typ;

Aber ohne eine Liste welche alle zu einem bestimmten Zeitpunkt installierten Pakete enthält, ist das Script natürlich sinnlos Das zweite Script legt eine der zur Wiederherstellung benötigten Listen an - man könnte diesen Code zur Listenerstellung z.B. in ein Backup-Script einfügen.

1
2
3
4
5
#!/usr/bin/bash
listpath="/mnt/backup/Paketlisten" # Pfad zu den Paketlisten
aktuell=`/bin/date +20%y-%m.%d-%H.%M`
typ=".list";
dpkg --get-selections | awk '!/deinstall|purge|hold/ {print $1}' > $listpath/$aktuell$typ;
Antworten |