Forum: PC-Programmierung Hilfe bei Bash-Skript -> doppelte Dateien durch Symlinks ersetzen


von Gerhard (Gast)


Lesenswert?

Hallo,

folgender Sachverhalt: Ein Firmen-Datei-Server muss mal grundsätzlich 
aufgeräumt werden, das Chaos nimmt überhand. Cheffe will die Notbremse 
ziehen und zukünftig auch mehr darauf achten, dass Ordnung in der 
Ordnerstruktur gehalten wird. Es gibt Teilbereiche, in denen eigentlich 
perfekte Ordnung herrscht und andere (insbesondere 
Entwicklungsabteilung), wo bald die Übersicht verloren geht.

Schritt 1 war das Schaffen einer neuen Ordnerstruktur auf einem anderen 
Netzlaufwerk und das Setzen des bisherigen Fileservers auf Read-Only.

Schritt 2 soll das Beseitigen von mehrfach vorhandenen Dateien auf dem 
alten Server sein. Sprich Dateien mit gleichem Inhalt, die mehrfach 
unter verschiedenen Namen in verschiedenen Verzeichnissen vorhanden 
sind. Es sollen alle Instanzen außer einer (beliebigen) gelöscht werden, 
wobei die gelöschten Dateien durch einen Symlink auf eben die eine nicht 
gelöschte Datei ersetzt werden sollen. Beim Kopieren auf den neuen 
Server bleiben dann lauter ins Leere zeigende Symlinks übrig, die 
anschließend gelöscht werden können.

Bisher haben wir mittels "fdupes" schon eine Textdatei mit den Namen der 
mehrfach vorhandenen Dateien erzeugt. Diese Textdatei ist übrigens 800 
MB groß, also kann man schonmal ganz gut das Problem erkennen.

Die Datei hat das folgende Format:

/srv/files/Benutzer/Stromberg_Bernd/Zeuch/Langweilig/letzte_Version.sch
/srv/files/Entwicklung/Projekte/PS-1200/CAD/Platinen/717-8210-001.sch
/srv/files/Entwicklung/Projekte/PS-1200/CAD/Platinen/717-8210-001.sch.ba 
k
/srv/files/Produkte/PS-1200/Unterlagen/ServiceManual/717-7210-001.sch

/srv/files/Benutzer/Steinke_Ulf/KantinenspeiseplanKW41.pdf
/srv/files/Benutzer/Heisterkamp_Berthold/KantinenspeiseplanKW41.pdf
/srv/files/Benutzer/Bursted_Erika/Leckerlecker!.pdf
/srv/files/Mitarbeiter+Soziales+Betriebsrat/KantinenspeiseplanKW41.pdf

Sprich, es gibt eine Auflistung aller gleichen Dateien mit jeweils einer 
Leerzeile dazwischen.

Was ich nun bräuchte, wäre ein Bash-Skript, welches das Löschen und 
Verlinken übernimmt. Hier komme ich nicht weiter. Ich kann mittels einer 
Schleife und "read" zwar die Zeilen in eine Variable einlesen, aber ich 
bekomme die große Schleife außenrum, quasi die "Pro-Datei-Schleife" 
nicht hin.

Danke für eure Hilfe!

von Myxo M. (myxom)


Lesenswert?

Gerhard schrieb:
> folgender Sachverhalt: Ein Firmen-Datei-Server muss mal grundsätzlich
> aufgeräumt werden, das Chaos nimmt überhand.

Stellt jemanden ein, der sich damit auskennt.

von olibert (Gast)


Lesenswert?

Sowas ist in Perl einfach machbar und sollte in Bash auch funktionieren:

o  Sobald eine Leerzeile kommt, Zeilen in ein Array einlesen, bis zur 
naechsten Leerzeile.

o  Schleife ueber Array:

   -Erstes Element im Array ignorieren

   -Alle nachfolgenden Elemente: Datei loeschen und Softlink mit 
gleichen   Namen der geloeschten Datei zu erstem Element erstellen

o  Array loeschen

o  Naechstes Array bis zum Leerzeichen oder EOF einlesen

von Hannes J. (Firma: _⌨_) (pnuebergang)


Lesenswert?

Das kannst du nicht komplett automatisieren, da ein Skript nur 
beschränkt entscheiden kann, welche von x identischen Dateien die eine 
sein soll, die aufgehoben werden soll.

Du darfst dich dann mit solchen Entscheidungen rumschlagen wie "alle 
.bak Dateien löschen, es sei denn es gibt eine Datei nur als .bak 
Dateien, ausgenommen wenn das Müll ist den niemand mehr braucht".

Oder soll der Speiseplan unter Kantine oder unter Soziales stehen 
bleiben?

Und was soll das Rumgemache in den Verzeichnissen der Benutzer? Ist das 
wirklich so ein Verbrechen, wenn sich Benutzer eine eigene Kopie des 
Kantinenspeiseplans anlegen?

Richte deinem Chef aus, diese Löschaktion kostet ihn mehr an Zeitaufwand 
und ist risikoreicher als der Kauf von ein paar weiteren Platten und 
Backup-Systemen. Und das er mal ein paar Regeln einführen soll, dass nur 
Projektdateien die im Projekt gespeichert sind, "gelten". Was Benutzer 
in ihrem Benutzerverzeichnis rumliegen haben sind "Experimente", die 
nicht "gelten" und von denen keine Veröffentlichungen (Neudeutsch 
Releases) gemacht werden dürfen. Das pisst dann die einsamen Helden an, 
aber was soll's? Dazu wäre dann mal ein Versionsverwaltungssystem fällig 
(noch mehr Plattenplatz und Backups).

von Gerhard (Gast)


Lesenswert?

Es geht hier um einen "Neuanfang", um ein untragbares Chaos zu 
beseitigen. Jeder Benutzer kann sich vom alten Server in sein neues 
Benutzerverzeichnis rüberkopieren, was immer er will. Und das 
entscheidet er auch alleine und Speisepläne sind nicht ausgeschlossen. 
Wie du sagtest, Benutzerverzeichnisse werden ab sofort als irrelevant, 
"tmp" o.ä. betrachtet und "zählen nicht".

Unser DMS verwaltet Verweise auf Dokumente und speichert dazu einen 
Hash. Sprich alles, was irgendwie relevant für den Laden ist ("gemanagte 
Dokumente"), wird ohnehin automatisch durch das DMS vom alten Server in 
die neue Ordnerstruktur kopiert. Interessanterweise liegt ein gewisser 
Anteil solcher wichtigen Dokumente in irgendwelchen 
Benutzerverzeichnissen. Das soll halt abgestellt werden.

Das Skript darf beim Löschen der redundanten Dateien tatsächlich eine 
ganz beliebige Kopie behalten, auch wenn die auf .bak endet und das 
Original gelöscht wird. Durch die Symlinks wird es ja weiterhin 
ansprechbar sein. Der alte Server ist - abgesehen von dieser Aktion - 
weiterhin read-only.

Ziel ist, nach der DMS-Verschiebeaktion mal zu schauen, was übrig 
bleibt. Wir wollen dann entscheiden, was ins DMS aufgenommen werden 
sollte und was gelöscht (oder wegarchiviert) werden kann.

von Thomas Z. (thomas_z41)


Lesenswert?

Macht
1
fdupes -l sym -r /srv
nicht genau das was du möchtest?

von Gerhard (Gast)


Lesenswert?

Mir ist noch keine fdupes-Version untergekommen, die die 
Kommandozeilenoption -l kennt. Verwechselst du da etwas?

von Irgendwer (Gast)


Lesenswert?

Gerhard schrieb:
> Das Skript darf beim Löschen der redundanten Dateien tatsächlich eine
> ganz beliebige Kopie behalten, auch wenn die auf .bak endet und das
> Original gelöscht wird. Durch die Symlinks wird es ja weiterhin
> ansprechbar sein.

Mal ein Beispiel - Du hast folgende Unterverzeichnisse:
Anwendung_V200_Release
Anwendung_V201_Release
Anwendung_V220_Release
Anwendung_V230_Release_Candidate
Anwendung_V240_SysTest
Anwendung_V250_Entwicklung
Anwendung_V300_Test_Maier
usw.

In all diesen gibt es z.B. eine irgendwas.cpp oder irgendeine.pdf
Nach deiner Philosophie würde dein Script alle davon bis auf eine 
löschen und in den anderen Verzeichnissen SymLinks anlegen.
Nur was ist jetzt wenn der Kollege Maier in seiner "Spielwiese" die 
irgendwas.cpp verändert?
Du hast Automatisch eine Änderung in allen anderen Verzeichnissen 
durchgeführt die dort aber überhaupt nicht gemacht werden dürfte!

Bloß weil es von einer Datei mehrere Kopien auf einem Rechner vorhanden 
sind heißt das noch lange nicht das die nach einer Veränderung auch 
weiterhin gleich bleiben sollen. Viel Spas dabei jedesmal dran zu denken 
vor einer Änderung die Links entsprechend aufzulösen.

von Gerhard (Gast)


Lesenswert?

Wie gesagt, Neuanfang. Diese alten Verzeichnisse werden alle Read-Only 
sein und niemand wird mehr in seinem Testverzeichnis etwas verändern. 
Das Entfernen von mehrfach vorhandenen identischen Dateien auf dem 
Dateiserver dient lediglich zur Erleichterung des Aufräumens. Die Anzahl 
der zu betrachtenden Dateien wird dadurch sehr deutlich reduziert.

Unsere Quelltexte liegen sowieso nicht im Verzeichnisbaum sondern haben 
ein separates CVS, Build- und Testsystem.

von c.m. (Gast)


Lesenswert?

kenne das problem: gib entwicklern platz und sie scheißen ihm zu.

warum muss das mit den links sein? ich würde vorschlagen du lässt den 
originalserver wie er ist, kopierst alle daten zum neuen server, und 
löschst dort mit
1
fdupes -fdN /ordner
alle dubletten bis auf die erste weg.

ein anderer weg wäre im ziel ein dateisystem mit integrierter 
deduplizierung zu nutzen, hab ich aber keine erfahrung mit und kann 
nichts empfehlen - außerdem löst sowas nicht den overhead beim 
(full)backup.

von c.m. (Gast)


Lesenswert?

da, schau mal ob dir das hilft. musst die inneren prints durch 
"system()" ersetzen und vorher prüfen wie dateinamen mit sonderzeichen 
(äöü/leerzeichen) behandelt werden.
1
#!/usr/bin/perl
2
use strict;
3
4
my $fdupes_infile='/home/asd/out.txt';
5
my @dups=();
6
7
open FILE, '<'.$fdupes_infile or die $!;
8
while (my $line = <FILE>) {
9
  chomp $line;
10
  if ($line =~ /^$/ ) {
11
    my $arrlen = @dups;
12
    print "Originaldatei: @dups[0]\n";
13
    for (my $numline = 1; $numline <$arrlen; $numline++) {
14
      my $dupfile = @dups[$numline];
15
      print "rm $dupfile\n";
16
      print "ln -s @dups[0] $dupfile\n";
17
    }
18
    @dups=();
19
  } 
20
  else {
21
    push(@dups,$line);     
22
  }
23
}

von Thomas Z. (thomas_z41)


Lesenswert?

Gerhard schrieb:
> Mir ist noch keine fdupes-Version untergekommen, die die
> Kommandozeilenoption -l kennt. Verwechselst du da etwas?

Ich verwende diese Version:
https://github.com/jobermayr/fdupes/tree/opensuse

von Peter II (Gast)


Lesenswert?

man könnte auch ganz anders rangehen.

Man benennt jede Datei nach ihrem SHA1 hash um. Diese legt man ein eine 
einfache Verzeichnisstruktur (3 oder 4 ebenen).

Jetzt kann man jeder Datei die man haben möchte, einfach den SHA1 
berechnen und dann prüfen ob es schon die "hash" Datei gibt, wenn nicht 
anlegen sonst einfach den links setzen. Damit würde das 
Anwender-Verzeichnis nur aus links bestehen.

Aber ich sehen noch ein anderes Problem, was ist wenn 2 Dateien gleich 
sind und eine Davon später geändert wird? Wie soll der Computer 
entscheiden ob beide Dateien sich ändern dürfen?

von Gerhard (Gast)


Lesenswert?

Danke Thomas und c.m.!

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.