PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Sed und ftp-upload



mhoffmann
19-06-2008, 09:34
Folgendes Problem:

In einem Verzeichnis soll rekursiv nach Dateien mit einem bestimmten Inhalt gesucht werden und jede dieser Dateien soll auf eine andere Maschine per ftp kopiert werden. Ist mit einem Einzeiler zu lösen:

grep -lre 'SUCHMUSTER' . | xargs ftp -u ftp://username:password@ftp.servername.de/uploaddir

Nun habe ich allerdings das Problem, dass die Dateinamen in den verschiedenen Quellverzeichnissen nicht unique sind, aber alle im gleichen Zielverzeichnis landen sollen. Das heisst ich müsste den remotefile-namen ändern. Der localfile-Name muss allerdings unangetastet bleiben.

Hat jemand einen Tip für mich? Ich bin leider auf der Kommandozeile blutiger Anfänger.

Danke für jeden Hinweis, Markus

jan61
19-06-2008, 19:05
Moin,

mit einem Einzeiler und der -u-Option des ftp kommst Du da wohl nicht weiter. Es hängt auch ein wenig davon ab, ob es egal ist, wie die Dateien auf dem Zielsystem heißen oder ob es Restriktionen / Wünsche bzgl. der Namen gibt. Man könnte z. B. die Dateinamen aus dem Verzeichnisnamen und Dateinamen zusammenbauen, oder einen eindeutigen Hash über den Verzeichnisnamen bilden und diesen als Dateinamenspräfix benutzen.

Es gibt verschiedene Varianten (das Zusammenspiel mit ftp habe ich nicht getestet), hier eine davon

Du benutzt ein sogenanntes HERE-Dokument (in der bash-Manualpage erklärt):

ftp ftp://username:password@ftp.servername.de/uploaddir <<!
> `grep -lre 'Suchbegriff' . | while read f; do echo "put '$f' '\`dirname \"$f\" | sed 's/^\.\///;s/\//_/g'\`_\`basename \"$f\"\`"'; done`
> !Was passiert hier? Das HERE-Dokument geht von der Zeichenkette "<<!" in Zeile 1 bis "!" in Zeile 3 (es ist wichtig, dass das ! allein in der letzten Zeile steht). Alles, was dazwischen liegt, wird an ftp übergeben und von diesem ausgeführt. Zeile 2 baut eine while-Schleife auf, die für jede von grep ermittelte Datei folgendes ftp-Kommando ausgibt: "put Quelldatei Zieldatei". Der Zieldateiname wird so gebildet, dass zuerst im Verzeichnisnamen der Quelldatei das führende "./" entfernt wird und dann jeder "/" in einen "_" verwandelt wird, anschließend wird noch der Dateiname angehängt. Die vielen verwirrenden Backslashes sind deshalb notwendig, weil Pfadnamen ja auch Leerzeichen enthalten können.

Wenn man statt des konvertierten Verzeichnisnamen einen Hash benutzt, vereinfacht sich die Sache etwas, allerdings ist dann im Ziel nicht mehr zu erkennen, woher die Datei stammt:

ftp ftp://username:password@ftp.servername.de/uploaddir <<!
> `grep -lre 'Suchbegriff' . | while read f; do echo "put '$f' '\`dirname \"$f\" | md5sum | tr -d ' '\`_\`basename \"$f\"\`"'; done`
> !Der zwischengeschummelte tr schafft das von md5sum eingefügte Leerzeichen aus der Welt.

Das Geraffel aus Zeile 2 kannst Du natürlich auch in ein kleines Shell-Script packen und dieses dann innerhalb des HERE-Dokuments aufrufen.

Andere Variante:
Du baust Dir ein temporäres Verzeichnis auf, in dem Du die Zielverzeichnis-Struktur per Link herstellst, dann kannst Du darüber den ftp rennen lassen (Variante mit Hash, ungetestet):


mkdir ../upload
grep -lre 'Suchbegriff' . | while read f; do
ln "$f" ../upload/"`dirname \"$f\" | md5sum | tr -d ' '`_`basename \"$f\"`"
done
cd ../upload
ls | ftp -u ftp://username:password@ftp.servername.de/uploaddir
cd ..
rm -r uploadDas waren nur ein paar Varianten mit reinen Shell-Mitteln, mit Perl & Co. gibt es sicher noch andere Varianten.

Jan

mhoffmann
19-06-2008, 19:43
Ich danke vielmals.... ich muss noch viel lernen...
Gruß, Markus