newbie versucht zu scripten

  • Hallo Coder,


    ich starte gerade meine ersten Gehversuche in der bash. Leider nur mit sehr mässigem Erfolg ;(


    Ich versuche alle Dateien unterhalb eines bestimmten Verzeichnis in Abhängigkeit der letzten Dateiänderung (> 5 min.)zu verschieben. Dazu habe ich folgendes Script erstellt, was aber leider alle Dateien verschiebt. Auch die, die jünger als 5 Minuten sind.


    Kann mir jemand sagen wo der Fehler ist?


    Hier das Script:


    #!/bin/bash


    if find /srv/share/incoming/* -mmin +5
    then
    echo $?
    chown -R vdr:vdr /srv/share
    chmod 0711 /srv/share/out
    chmod 0733 /srv/share/incoming
    touch /srv/share/incoming/dummy
    mv -f /srv/share/incoming/* /home/vdr/incoming/
    echo "file moved"
    exit 0
    else
    echo $?
    echo "directory empty"
    exit 1
    fi


    vielen Dank für die Hilfe
    mav

  • bitte code zwischen [ code ] und [ /code ] einschliessen. Dann sieht es so aus:



    so etwas sollte gehen:

    Code
    find /srv/share/incoming -mmin +5 -exec mv \{\} /foo/bla \;


    dies verschiebt alle Dateien aus /srv/share/incoming, die aelter sind als 5 minuten, nach /foo/bla

  • Vielen Dank für die Antwort.


    Das funktioniert soweit ganz gut. Wenn ich aber mehrere Kommandos auf evtl. vohandene Dateien anwenden möchte, klappt das mit der -exec Option nicht mehr.


    Die if Anweisung liefert mir immer ein true zurück wenn eine Datei im angegebenen Pfad vorhanden ist. Unabhängig vom Alter.


    mav

  • Zitat

    Original von maverick
    Vielen Dank für die Antwort.


    Das funktioniert soweit ganz gut. Wenn ich aber mehrere Kommandos auf evtl. vohandene Dateien anwenden möchte, klappt das mit der -exec Option nicht mehr.


    dann leg einfach ein Skript an, welches alle benoetigten Kommandos mit der einen Datei macht und rufe es per exec auf

  • Jau das isses :]


    Ich habe Stunden damit verbracht eine Lösung mit if-then-else zu finden. Manchmal muss man einfach etwas weiter denken und nach Alternativev suchen.


    Noch mal vielen Dank für die Hilfe.


    mav

  • Zitat

    Original von maverick
    Die if Anweisung liefert mir immer ein true zurück wenn eine Datei im angegebenen Pfad vorhanden ist.


    Klar.
    Erklärung:
    Das if- Statement prüft nicht, ob ein Befehl etwas ausgibt, sondern nur, ob ein Befehl erfolgreich ausgeführt wurde. Stichwort: Rückgabewert bzw. Errorlevel.
    Dein find- Befehl wurde natürlich erfolgreich ausgeführt, weswegen if ein "OK" zurückbekommen hat und die Schleife ausgeführt wurde. Habe ich mich verständlich machen können?


    Den richtigen Weg hast Du ja schon bekommen. Mit Hilfe der for- Schleife läßt sich so etwas wunderbar machen. Es gibt aber noch tausend andere Wege, das zu realisieren. Bash macht's möglich!


    Du könntest z.B. Deine mehreren Befehle zu einer function zusammenfassen und diese dann direkt mittels find und -exec ausführen lassen. Oder mittels ls, grep und cut die Dateinamen finden, oder oder oder...


    Viel Spaß beim Skripten- das ist wie der VDR: einmal angefangen, shcon hat einen die Sucht gepackt :)

    Glotze: yaVDR (ASRock Q1900M, 4GB RAM, DD Cine S2 V6.5, ZOTAC GT630 (Rev. 2)
    Server: HP ProLiant MicroServer G8, VMware ESXi 5.5 :P

  • Dem schafft ein vorheriges

    Code
    IFS='
    '


    (einfach zwischen den Anfuehrungszeichen ein Return ...)


    Abhilfe. IFS gibt den Trenner fuer for und anderes an und enthaelt normalerweise return, space und tab .


    Weiterhin solltest Du u.U. $file in doppelte anfuehrungszeichen zu setzen.


    Am einfachsten wird's, wenn man einfach Leerstellen in Dateinamen vermeidet und diese durch Unterstriche ersetzt ...


    Gruss


    /elle

  • Zitat

    Dem schafft ein vorheriges

    Code
    IFS='
    '


    (einfach zwischen den Anfuehrungszeichen ein Return ...)


    Abhilfe.


    .... aber bitte nicht so. Das kann doch später im Listing keiner mehr lesen. So geht das:

    Code
    IFS=$'\n'

    Ansonsten wie immer der Hinweis: Schaut euch die Programming Corner im LinuxUser an, da wird alles erklärt, was man für die Bash-Programmierung brauchen kann. Die ersten sieben Teile sind online, teilweise die Nachfolgeteile ebenfalls.


    Viele Grüße, Mirko

  • Zitat
    Code
    for file in `find . -mmin +5`; do echo move $file to bar; mv $file bar ; done


    Ich will in meinem Sicherungverzeichnis alle Daten löschen, die älter als x Tage sind. Das wäre ja mit obigen Code schön möglich. Gleichzeitig sollen jedoch immer drei Sicherungsdateien mindestens vorhanden sein.


    Wie mach ich das am einfachsten?



    Grüße
    Fux

    Hardware: Asus M3N78-EM µATX GF 8300 | AMD Sempron 140 | Display VFD USB MDM166A | DVB-S2 TT-3600 USB | RAM 1 GB | WD20EARS 2 TB
    Software: yaVDR 0.5

    Einmal editiert, zuletzt von Fux ()

  • Zitat

    Das if- Statement prüft nicht, ob ein Befehl etwas ausgibt, sondern nur, ob ein Befehl erfolgreich ausgeführt wurde. Stichwort: Rückgabewert bzw. Errorlevel.


    knebb
    Vielen Dank für die Erklärung. Langsam kommt Licht ins Dunkel. Die Lösung hat mir zwar erstmal weiter geholfen, aber erst jetzt habe ich verstanden warum es mit der IF Anweisung nicht funktioniert hat.


    @all
    Kennt jemand gute Literatur die mir den Einstieg etwas erleichtert? Eine einfache Befehlsreferenz ist dafür wohl nicht ausreichend.


    mav



    P.S. Die Artikel von Mirco (cooper) habe ich zwischenzeitlich gelesen.

  • Zitat

    Original von Fux
    Ich will in meinem Sicherungverzeichnis alle Daten löschen, die älter als x Tage sind. Das wäre ja mit obigen Code schön möglich. Gleichzeitig sollen jedoch immer drei Sicherungsdateien mindestens vorhanden sein.


    Nur die Idee und Werkzeuge dazu:


    Mittels ls nach Datum sortieren, die neuesten unten. tail -n 3 zeigt nur die letzten drei an. Die dann z.B. verschieben in ein tmp- Dir. Danach einfach wie oben löschen, die drei wieder herschieben.


    Keine besonders elegante Lösung, aber wird funktionieren.

    Glotze: yaVDR (ASRock Q1900M, 4GB RAM, DD Cine S2 V6.5, ZOTAC GT630 (Rev. 2)
    Server: HP ProLiant MicroServer G8, VMware ESXi 5.5 :P

    Einmal editiert, zuletzt von knebb ()

  • Habs jetzt mal so gemacht wie knebb vorgeschlagen hat. Ganz optimal ist es natürlich mit der Kopiererei nicht, aber wenns nur kleine Sachen sind, dann gehts :)
    Ansonsten bitte Alternativen.



    Kriegt man die Fehlermeldung

    Code
    cp: omitting directory `temp'


    eigentlich irgendwie weg?
    Und wie heißt denn in der BASH die "if not" Funktion?


    EDIT: Wie bekomm ich denn ins Datum die Uhrzeit in der Form 14.00 statt 14:00, weil da gibts ja Probleme.


    Gruß
    Fux

    Hardware: Asus M3N78-EM µATX GF 8300 | AMD Sempron 140 | Display VFD USB MDM166A | DVB-S2 TT-3600 USB | RAM 1 GB | WD20EARS 2 TB
    Software: yaVDR 0.5

    4 Mal editiert, zuletzt von Fux ()

  • Code
    for file in `ls -tr | tail -n 2`; do cp $file $TEMPSICH; done


    1. Wolltest Du nicht drei (3) aufheben, anstatt zwei (Tippfehler?)
    2. Nimm besser kein cp, sondern ein mv. Geht auf der gleichen Partition WESENTLICH schneller.


    Code
    tar czf $ZIELSICH/$SICHNAME.tar.gz $SICHTYP


    Noch ein "p" dazu und anstelle des "z" besser ein "j": tar cpjf ...
    p: behält die Dateirechte und Eigentümer
    j: Nimmt zur Komprimierung bzip2 anstatt gzip. bzip2 komprimiert besser (aber langsamer) und ist toleranter gegenüber Bitfehlern

    Zitat

    Und wie heißt denn in der BASH die "if not" Funktion?


    man test
    Nochmal:
    if prüft den Rückgabewert eines Befehls führt nur ein test aus. Die Schreibweise ist nur eine Vereinfachung für if [test ...] then...


    Ansonsten ist noch als Buch dazu zu empfehlen:
    Linux in a Nutshell von O'Reilly

    Glotze: yaVDR (ASRock Q1900M, 4GB RAM, DD Cine S2 V6.5, ZOTAC GT630 (Rev. 2)
    Server: HP ProLiant MicroServer G8, VMware ESXi 5.5 :P

  • Zitat

    1. Wolltest Du nicht drei (3) aufheben, anstatt zwei (Tippfehler?)


    Naja, die Sicherung kommt ja erst zuletzt und dann sinds ja drei Stück :D


    Zitat

    2. Nimm besser kein cp, sondern ein mv. Geht auf der gleichen Partition WESENTLICH schneller.


    Oh, ist klar.


    Danke für die restlichen Hinweise :)

    Hardware: Asus M3N78-EM µATX GF 8300 | AMD Sempron 140 | Display VFD USB MDM166A | DVB-S2 TT-3600 USB | RAM 1 GB | WD20EARS 2 TB
    Software: yaVDR 0.5

    Einmal editiert, zuletzt von Fux ()

  • mit

    Code
    ls -tr | head -n -2

    bekommst du alle Dateien bis auf die neuesten zwei.


    das ganze koennte also (in etwa) so aussehen:

    Code
    touch -d "7 days ago" .
    for file in `ls -tr | head -n -2` ; do test "$file" -ot . && rm "$file" ; done


    EDIT: IFS rausgenommen, da damit ls nicht ging.


    PS: immer mit Dateien mit Leerzeichen aufpassen!

  • Zitat

    das ganze koennte also (in etwa) so aussehen:

    Code
    touch -d "7 days ago" .  
    for file in `ls -tr | head -n -2` ; do test "$file" -ot . && rm "$file" ; done


    Wirklich sehr raffiniert :P
    Dankeschön!



    Gruß
    Fux

    Hardware: Asus M3N78-EM µATX GF 8300 | AMD Sempron 140 | Display VFD USB MDM166A | DVB-S2 TT-3600 USB | RAM 1 GB | WD20EARS 2 TB
    Software: yaVDR 0.5

    6 Mal editiert, zuletzt von Fux ()

Jetzt mitmachen!

Sie haben noch kein Benutzerkonto auf unserer Seite? Registrieren Sie sich kostenlos und nehmen Sie an unserer Community teil!