• Willkommen im Linux Club - dem deutschsprachigen Supportforum für GNU/Linux. Registriere dich kostenlos, um alle Inhalte zu sehen und Fragen zu stellen.

[GELÖST] kleines Skript für Dateiübertragung-backup

Znarf

Member
Hallo Linuxspezialisten,

ich bräuchte eine kleine "Programmierhilfe" zur Optimierung folgenden einfachen Skripts:

Code:
#!/bin/bash
mv /home/user/Kalender/std.ics /home/user/Kalender/std.ics-save
cp /media/xyz/std.ics /home/user/Kalender/

Auf dem Rechner ist /home/user/Kalender/std.ics als Standard-Kalender (korganizer) eingerichtet.
Damit übertrage ich gelegentlich Kalenderdateien von einem usb-Stick von einem anderen Rechner (ich will hier keinen Abgleich über Server etc. und brauche keine Synchronisation).
Wenn nun etwas schiefgeht, kann ich auf "std.ics~save" zurückgreifen, aber natürlich nicht mehr beim zweiten Mal, wenn unbemerkt was schieflaufen sollte. Ich würde das Skript nun gerne so abändern, dass die jeweils alte std.ics auf dem Rechner durch automatisches Umbenennen immer "behalten" wird, etwa nach diesem Prinzip:

mv beim 1. Übertrag: std.ics --> std.ics~save1
mv beim 2. Übertrag: std.ics~save1 --> std.ics~save2 und std.ics --> std.ics~save1
mv beiim 3. Übertrag: std.ics~save2 --> std.ics~save3 und std.ics~save1 --> srd.ics~save2 und std.ics --> std.ics~save1 usw., danach jeweils der cp-Befehl.

Nach etwa z.B. 10 Übertagungen könnte man die Kette abbrechen lassen (d.h. die älteste std.ics~save Datei könnte runterfliegen).

Ich vermute mal, dass sich das rel. einfach programmieren ließe, wenn man davon Ahnung hätte; das ist bei mir leider nicht der Fall. Deshalb wäre ich sehr dankbar, wenn mir jemand helfen könnte.

Viele Grüße


Z.
 

RME

Advanced Hacker
Hallo,

Wie üblich mit Linux gibt es for Dein Problem viele mögliche Lösungen.

-1- Ein selbsterstelltes Script welches genau das macht was und wie Du es möchtest. Stichwort: editiere die Dateinamen mit dem 'sed' Editor.

-2- Einfacheste Lösung: siehe man pages für 'cp'

z.B.

Code:
cp --backup=numbered xyz.txt abc.txt
gibt dann (nach mehrmaliger Anwendung) sowas:

Code:
abc.txt
abc.txt.~1~
abc.txt.~2~
abc.txt.~3~
etc.

Gruss,
Roland
 
OP
Z

Znarf

Member
Vielen Dank. Die cp man page ist ja einigermaßen verständlich, das werde ich probieren und wieder berichten. "sed" ist für mich eine Nummer zu groß, das übersteigt meine erlernbaren Linuxfähigkeiten um ein Vielfaches!

Gruß Z.
 
OP
Z

Znarf

Member
Okay, das funktioniert prima, nochmals vielen Dank.
Um die Datenmengen zu begrenzen, würde ich gerne sagen wir mal ab der 10. oder 20. Sicherung gerne die ältesten "herunterwerfen". Gibt es dafür auch eine einfache Syntax, z.B. mit rm ? Hier sagt die man nicht so viel aus, oder genügt es, wenn ich z.B. den Befehl
Code:
rm std.vcf~20~
anhänge, damit ich immer nur 19 Sicherungsdateien (und nicht mehr) habe?

Gruß Z.
 

RME

Advanced Hacker
Nein so gehts leider nicht, weil:

Code:
std.vcf
std.vcf.~1~
std.vcf.~2~
std.vcf.~3~
...
std.vcf.~20~
std.vcf die letzte (neueste) Version

und

std.vcf.~1~ die älteste Version
std.vcf.~2~ die zweit-älteste Version
...
std.vcf.~20~ die zweit-neueste Version ist.

Du müsstest also "von unten her" (1, dann 2, dann 3) löschen.

Gruss,
Roland
 
OP
Z

Znarf

Member
Oh je, dann wirds doch komplexer, weil ich ja bei den ersten 20x die std.vcf~1~ ja gerade nicht löschen möchte, sondern erst danach. Idee ??

Gruß Z.
 

RME

Advanced Hacker
Hallo,

Ich habe ein einfaches bash script geschrieben welches Du mal testen könntest. Aber bitte beachte: ich habe das script nur oberflächlich getestet und überneme keinerlei Verantwortung.

Das script wird so aufgerufen:

Code:
./cpbkup <woher>/daten.vcf <wohin>/old_data.vcf
oder
Code:
sh cpbkup <woher>/daten.vcf <wohin>/old_data.vcf
(die Dateinamen sind natürlich wie auch immer)

Code:
Die neuste backup-Datei wird heissen: old_data.vcf.~1~
Die zweit-neuste:                     old_data.vcf.~2~
...
Die älteste:                          old_data.vcf.~10~
Wenn eine neue backup-Datei erzeugt wird, dann werden die bestehenden um eine Versions-Nummer heraufgestzt, bis zur maximalen version, welche aktuell auf "10" gesetzt ist. Wenn noch ältere Versionen existieren (old_data.vcf.~11~ oder höher) werden diese ignoriert.

Die maximale Versionen-Zahl kannst Du im script ändern wenn Du möchtest... die Zeile:

Code:
max_bkups=10
(9te Zeile von oben) entsprechen editieren.

Erstelle das script mit copy/paste in eine Text-Datei (nenne diese dann "cpbkup" oder wie Du willst) und mache das script ausführbar:

Code:
chmod +x cpbkup
>>> teste das script zuerst an Dateien von welchen Du bereits backups gemacht hast.

Hier der Code:

Code:
#! /bin/bash
# cpbkup
#
# (make script executable with: chmod +x cpbkup)
#
# Very simpleminded backup utility with version numbers.
#

max_bkups=10

ARGS=2

if [ $# -ne "$ARGS" ]
then
  echo "  usage: `basename $0` input output"
  echo "example: `basename $0` abc/xyz/data.txt backup/old_data.txt"
  exit 0
fi

if test ! -f "$1"
then
  echo "input file does not exist"
  exit 0
fi

# ========== move existing backups to a higher version (e.g. ~3~ to ~4~)
#+           but at most up to "max_bkups" (any higher versions are ignored)

COUNTER=$((max_bkups-1))
while [ $COUNTER -gt 0 ]; do
  filename=$2.~"$COUNTER"~
  if [ -f "$filename" ]
  then
    new_version=$(($COUNTER+1))
    mv $filename $2.~"$new_version"~
  fi
  let COUNTER=COUNTER-1
done

# ========== make new backup with version number ~1~

cp $1 "$2.~1~"

exit 0

# ========== end of script
Gruss,
Roland

Nachtrag: das script wurde zuletzt editiert: 21.11.2001, 1700Uhr
 
OP
Z

Znarf

Member
Ich glaub, ich schließ den Thread besser mal und setz ihn auf gelöst; für das "neue" Problemchen mach ich einen extra Thread auf- Gruß Z.
 
OP
Z

Znarf

Member
Ah, da war ich wohl zu voreilig. Ganz herzlichen Dank für das Testskript. ich werde es heute ausprobieren, sobald Zeit ist, und wieder berichten. Schade, dass ich so wenig davon verstehe....
 
OP
Z

Znarf

Member
Hallo Roland und andere Interessierte,

ich habe das Skript jetzt an einem "Testordner" so modifiziert (Z.15 und 16) und ausführbar gemacht
Code:
#! /bin/bash
# cpbackup_ics_vcf
#
# (make script executable with: chmod +x cpbkup)
#
# Very simpleminded backup utility with version numbers.
#

max_bkups=12

ARGS=2

if [ $# -ne "$ARGS" ]
then
  echo "  usage: `basename $0` /home/franz/ZKalender/std.ics /home/franz/ZKalender/backup/old_std.ics"
  echo "example: `basename $0` /home/franz/ZKalender/std.ics /home/franz/ZKalender/backup/old_std.ics"
fi

if [ -f "$1" ]
then
  in_name=`basename $1`            # Strip off path.
  out_name=`basename $2`           # Strip off path.
else
  echo "input file does not exist"
  exit 0
fi

# ========== move existing backups to a higher versio (e.g. ~3~ to ~4~)
#+           but at most up to "max_bkups" (any higher versions are ignored)

COUNTER=$((max_bkups-1))
while [ $COUNTER -gt 0 ]; do
  filename=$2.~"$COUNTER"~
  if [ -f "$filename" ]
  then
    new_version=$(($COUNTER+1))
    mv $filename $2.~"$new_version"~
  fi
  let COUNTER=COUNTER-1
done

# ========== make new backup with version number ~1~

n=`echo $1 | sed -e "s/$in_name/$out_name/"`
cp $1 "$2.~1~"

exit 0

# ========== end of script

Das scheint prinzipiell zu funktionieren, in das backup-Verzeichnis werden die alten .vcf Dateien weggesichert, und ~1~ ist die neueste Sicherungskopie. Ich hoffe, die "usage" und "example" Zeilen wurden richtig interpretiert.

So, jetzt muss ich aber irgendwie beide Ansätze zusammenbringen:
Zunächst kopierte ich mir ja std.ics und std.vcf in ein Verzeichnis mit den Backups. Hier das zugehörige Beispielsskript:
Code:
cp --backup=numbered /home/franz/Adressbuch/std.vcf /home/franz/ZAdressbuch/std.vcf
cp --backup=numbered /home/franz/Kalender/std.ics /home/franz/ZKalender/std.ics
Damit erzeuge ich nun in .../Zkalender bzw. .../ZAdressbuch dennoch unendlich viele Sicherungskopien des Musters std.ics~1~ usw. (was ich ja eigentlich nicht will)

Wie kann ich beide Vorgänge zusammenfassen (also std.ics in ZKalender erzeugen, die vorher dort existierende std.ics nach std.ics~1~ ändern und diese dann ins Backupverzeichnis ../backup rüberschieben nach dem Muster, wie es Roland beschrieben hat (mit Begrenzung nach oben usw.)
Dann würde ich gerne neben std.ics dasselbe mit std.vcf ausführen, kann ich dafür hinter Z. 15 und 16 das einfach ergänzen ?
Code:
  echo "  usage: `basename $0` /home/franz/ZKalender/std.ics /home/franz/ZKalender/backup/old_std.ics"
  echo "example: `basename $0` /home/franz/ZKalender/std.ics /home/franz/ZKalender/backup/old_std.ics"
  echo "  usage: `basename $0` /home/franz/Adressbuch/std.vcf /home/franz/ZAdressbuch/backup/old_std.vcf"
  echo "example: `basename $0` /home/franz/Adressbuch/std.vcf /home/franz/ZAdressbuch/backup/old_std.vcf"
fi

Zuletzt wäre es natürlich optimal, wenn ich den über die Kommandozeile eingegebenen Backupbefehl, des jetzt so ausssieht:
Code:
~/ZKalender> ./cpbackup_ics_vcf /home/franz/ZKalender/std.ics /home/franz/ZKalender/backup/old_std.ics
ebenfalls in einem Skript hätte. Kann ich mir dazu ein Shellskript anlegen mit sh .../ZKalender/cpbackup_ics-vcf ?

Sorry, das mich das Ganze absoluter Laie evtl. doch etwas (über?)fordert, aber vielleicht seh ich jetzt den Wald vor Bäumen nicht mehr. Jedenfalls vielen Dank für Eure/Deine Mühen und Hilfestellungen, ggf. auch künftige!

Gruß Z.
 

RME

Advanced Hacker
Hallo,

Also zunächst: was Du da in Zeilen 15... geändert bzw. eingefügt hast ist ohne Wirkung. Zeilen welche mit "echo" beginnen sind lediglich Kommentare welche auf der Konsole angezeigt werden. In meinem (original) script sind jene Zeilen als Hilfe für den User gedacht.

Gib mal in der Konsole den (absichtlich incorrekten) Befehl ein:

Code:
./cpbkup abc
Du siehst jezt die Ausgabe der "echo" Zeilen.

Oder, gib den Befehl ein mit einer Eingabe-Datei welche nicht existiert:

Code:
./cpbkup abc123 ./test.txt
Auch hier, die Ausgabe des "echo" von Zeile 24 (mein original script).

----------

Um Deine Dateien wegzupaken brauchst Du jetzt den "cp --backup=numbered" Befehl nicht mehr.

Also lediglich:

Code:
./cpbkup /home/franz/Adressbuch/std.vcf /home/franz/ZAdressbuch/std.vcf
./cpbkup /home/franz/Kalender/std.ics /home/franz/ZKalender/std.ics
oder, etwas kürzer:

Code:
./cpbkup ~/Adressbuch/std.vcf ~/ZAdressbuch/std.vcf
./cpbkup ~/Kalender/std.ics ~/ZKalender/std.ics
('~' ist an Stelle von "/home/franz")

Beispiel (bei mir):

Code:
./cpbkup data.txt ~/RME/old/xyz.txt
./cpbkup xcx.txt ~/RME/old/xyz.txt
./cpbkup 123.txt ~/RME/old/xyz.txt
./cpbkup dlnc.txt ~/RME/old/xyz.txt
erzeugt:

Code:
ls -l ~/RME/old
total 16
-rw-r--r-- 1 user0 users 657 Nov 21 11:53 xyz.txt.~1~
-rw-r--r-- 1 user0 users 657 Nov 21 11:53 xyz.txt.~2~
-rw-r--r-- 1 user0 users 657 Nov 21 11:53 xyz.txt.~3~
-rw-r--r-- 1 user0 users 657 Nov 21 11:53 xyz.txt.~4~
xyz.txt.~1~ ist die neuste backup Datei = dlnc.txt
...
xyz.txt.~4~ die älteste backup Datei = data.txt

(max "max_bkups" Dateien)

Gruss,
Roland
 
OP
Z

Znarf

Member
Hallo Roland,

damit bin ich einen Schritt weiter, aber noch nicht ganz am Ziel. Wenn ich
Code:
./cpbkup ~/Adressbuch/std.vcf /~/ZAdressbuch/std.vcf
./cpbkup ~/Kalender/std.ics ~/ZKalender/std.ics
eingebe, werden zwar die Sicherungen in ~/ZKalender bzw. ~/ZAdressbuch durchgwführt wie gewünscht (bis zu den jetzt maximal eingestellten 12), aber die Dateien std.vcf und std.ics aus ~/Adressbuch bzw. ~/Kalender werden NICHT nach ~/ZKalender bzw. ~/ZAdressbuch kopiert; d.h. es werden lediglich immer Sicherungskopien der in ~/ZKalender bzw. ~/ZAdressbuch bereits vorhandenen "alten" std. ics bzw. std.vcf gemacht. Wenn ich testweise std.ics und std.vcf aus ZKalender und ZAdressbuch entferne, passiert nichts (also keine neue std.ics oder std.vcf wird dort angelegt).

???

Der Hintergrund der ganzen Prozedur ist übrigens, dass ich auf das ZAdressbuch und ZKalender-Verzeichnis einen Netzwerkzugriff eingerichtet habe, um die Dateien auch auf mehreren anderen Rechnern zur Verfügung zu haben. Diesen Zugriff möchte ich aber nicht auf meine als "Standards" eingerichteten Verzeichnisse (Adressbuch und Kalender) erlauben.


Gruß Znarf
 

RME

Advanced Hacker
Hallo,

... d.h. es werden lediglich immer Sicherungskopien der in ~/ZKalender bzw. ~/ZAdressbuch bereits vorhandenen "alten" std. ics bzw. std.vcf gemacht...
Bist Du sicher? Bei mir funktioniert das script wie es soll! :D

Wenn Du (testhalber) immer die gleiche Datei nach "~/ZAdressbuch" (bzw. ~/ZKalender) kopierst, dann ist es nicht ganz offensichtlich was genau geschieht. Versuchs mit verschiedenen (input-)Dateien, d.h. verschiedener Grösse oder verschiedenem Inhalt, dann siehst Du besser was wohin geht.

Roland
 
OP
Z

Znarf

Member
Ah ja, habe das jetzt mal so probiert
Code:
./cpbackup_ics_vcf ~/Adressbuch/std.vcf~save2011-11-10 ~/ZAdressbuch/abc.vcf
und es wird eine Sicherungsdatei abc.vcf.~1~ erzeugt. Hier hätte ich aber gerne auch die "neue" abc.vcf bzw. später std.vcf (die "alte" soll hier überschrieben werden! Nur die "alte" soll weggesichert werden, damit die neue die alte überschreiben darf - in dieser Reihenfolge).

Wenn ich das doch mit zuerst:
Code:
./cpbackup_ics_vcf ~/ZAdressbuch/std.vcf ~/ZAdressbuch/backup/old_std.vcf
mache und dann einfach ein
cp ~/Adressbuch/std.vcf. ~/ZAdressbuch/std.vcf
sozusagen erzwingen würde; dann hätte ich doch die "alte" std.vcf in ~/ZAdressbuch zunächst gesichert (nach.../backup), und dann würde der cp-Befehl (ohne das --backup=numbered Argument) die "alte" std.vcf in ~/Zadressbuch überschreiben - oder mach ich da wieder einen Denkfehler ?

Falls es so geht, könnte ich den cp-Befehl im Skript (vor exit 0) noch anfügen?

Gruß Z.
 
OP
Z

Znarf

Member
Ich habe das mal auf der Konsole hintereinander ausgeführt (Dein Skript --> wegsichern nach ~/Zadressbuch/backup), und dann das ordinäre cp ohne irgendwelche Argumente, das die "alte" std.vcf entsprechend überschreibt); scheint so zu passen.

Ich versuch das, jetzt noch in ein einheitliches Skript zu zwängen und werde berichten, ob das dann so funktioniert.

Gruß Z.
 
OP
Z

Znarf

Member
Also, dieses Skript
Code:
#!/bin/bash
# Dies ist ein Skript, das die Kalender- und Adressbuchdateien std.ics und std.vcf im Homenutzerverzeichnisse "ZKalender" und "ZAdressbuch" wegsichert und dann eine neue std.ics bzw. std. vcf in ZKalender bzw. ZAdressbuch erzeugt.

sh /home/franz/ZKalender/cpbackup_ics_vcf /home/franz/ZAdressbuch/std.vcf /home/franz/ZAdressbuch/backup/std.vcf
sh /home/franz/ZKalender/cpbackup_ics_vcf /home/franz/ZKalender/std.ics /home/franz/ZKalender/backup/std.ics
sleep 3
cp /home/franz/Adressbuch/std.vcf /home/franz/ZAdressbuch/std.vcf
cp /home/franz/Kalender/std.ics /home/franz/ZKalender/std.ics
mit der genialen Anleitung von Roland (nochmals Dank dafür und Respekt: da weiß jemand, was man wie anfassen muss!) für das cpbackup_ics_vcf - macht jetzt das, was ich möchte.

der cp Befehl ist vlt. etwas brachial - wenn jemand noch eine bessere Idee hat, bitte gerne noch Posting. Ich lasse den Thread solange noch offen.

Gruß Znarf
 

RME

Advanced Hacker
Hallo,

Ich habe das script noch etwas bereinigt -- da war noch unnötiger code drin (vom experimentieren). Ich habe es oben editiert. Bitte vergleichen (am Resultat ändert sich allerdings nichts).

----------

Deine letzten Postings habe ich (so ich hoffe) verstanden. Im Prinzip möchtest Du folgendes:

Code:
~/Adressbuch/std.vcf                  (a)

~/ZAdressbuch/std.vcf                 (b)

~/ZAdressbuch/backup/std.vcf.~1~      (c)
                    /std.vcf.~2~
                    /std.vcf.~3~
                    etc.
Nun soll:

-1- cpbkup (b) --> (c) --- (mit version number)

-2- cp (a) --> (b)

Stimmts?

Wenn ja, hier noch ein Versuch:

Code:
#! /bin/bash
# cpbkup
#
# (make script executable with: chmod +x cpbkup)
#
# Very simpleminded backup utility with version numbers.
#
# cpbkup xyz/data1.txt abc/data2.txt backup/old_data.txt
#
# cp <bbb>/data_file --> <backup>/bkup_file  (a version number will be added)
# cp <aaa>/data_file --> <bbb>/data_file

max_bkups=10

ARGS=3
bkup=1

if [ $# -ne "$ARGS" ]
then
  echo "  usage: `basename $0` input_1 input_2 output"
  echo
  echo "example: `basename $0` <aaa>/data_1_file <bbb>/data_2_file <backup>/bkup_file"
  echo
  echo "cp <bbb>/data_file --> <backup>/bkup_file  (a version number will be added)"
  echo "cp <aaa>/data_file --> <bbb>/data_file"
  echo
  exit 0
fi

if test ! -f "$1"
then
  echo "input file (first calling argument) does not exist"
  exit 0
fi

if test ! -f "$2"
then
  echo "input file (second calling argument) does not exist"
  echo "--- no backup will be made to $3 ---"
  bkup=0
fi

if [ $bkup -eq 1 ]
  then

# ========== move existing backups to a higher version (e.g. ~3~ to ~4~)
#+           but at most up to "max_bkups" (any higher versions are ignored)

  COUNTER=$((max_bkups-1))
  while [ $COUNTER -gt 0 ]; do
    filename=$3.~"$COUNTER"~
    if [ -f "$filename" ]
    then
      new_version=$(($COUNTER+1))
      mv $filename $3.~"$new_version"~
    fi
   let COUNTER=COUNTER-1
  done

# ========== make new backup of input_2 with version number ~1~

  cp $2 "$3.~1~"
fi

# ========== copy input_1 to input_2

cp $1 "$2"

exit 0

# ========== end of script
Der Aufruf wäre (jetzt drei Argumente):

Code:
./cpbkup_new ~/Adressbuch/std.vcf ~/ZAdressbuch/std.vcf ~/ZAdressbuch/backup/std.vcf
Gruss,
Roland
 
OP
Z

Znarf

Member
Wow, was soll ich sagen !? Das läuft perfekt; ganz großes Kompliment und Dankeschön (hab fast schon ein schlechtes Gewissen, woanders muss man Software teuer erstehen).

Ich stell den Thread dann mal auf gelöst.

Viele Grüße Znarf
 
Oben