• 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] Dateien archivieren und löschen!

Hk95

Newbie
Hallo Liebe Community!
Bin noch recht neu dabei bei der Programmierung und komme bei meiner Aufgabe nicht weiter. Ich probiere ein Shell-Skript zu erstellen was Dateien aus einem Verzeichnis einliest und in eine zip packt. Dabei soll Dateien berücksichtigt werden die älter als X Tage sind. Für jede zu verpackende Datei will ich dabei den User fragen ob er die Datei archivieren und löschen soll oder nicht.

Ich kopier den Programmcode mal rein, ich weiß das meine Einrückung nicht optimal ist, mir würde es aber sehr weiterhelfen wenn ihr mich auf meine Fehler im Code aufmerksam machen könnt!

Vielen Lieben Dank im Vorraus!
LG Hans

Code:
#!/bin/bash
  
#Nutzereingabe für Alter der Dateien
echo "How old should the files be?"
read Number_days

        if ! [[ "$Number_days" =~ [0-9]+$ ]];then
                echo "Error, only enter a number please!"
fi

#Mindestalter der Dateien filtern und ausgeben
Files=$(find -mtime +$Number_days)
echo $Files

#Durchgehen der Dateien
Archive="packed.zip"
Counter=0
        for File in $Files
                do
                echo -n "Do you want to archive <$File>?(y/n):"
                read Decision
                done

#Überprüfung der Nutzereingabe und Fallunterscheidung
        if [ "$Decision" != "y" ] || [ "$Decision" != "n"]; then
                echo -e "No proper Input recognized! Please only enter y or n!\a"

                elif [ "$Decision" = "n" ]; then
                        echo -e "skipped current Fie!\a"
                        continue

                        #Bestätigung der Nutzereingabe positiv: Datei wird verschoben und gelöscht
                elif ["$Decision" = "y" ]; then
                        echo "File will be archived, deleting the original one!"
                        zip "$Archive" $File
                        let Counter++           #Inkrementierung Counter für zählen der Dateien!
                        rm $File
                else
                echo "Wrong Input!"     
        fi

#Bestätigung am Ende
echo "$Counter File(s), older then $number_days were successfully put in the <$Archive>"

exit 0
 

abgdf

Guru
Hallo,

- Deine RegEx sieht irgendwie nicht gut aus.
- Deine y/n-Abfrage stimmt nicht: != "y" && != "n"
- Wenn nur noch "y" oder "n" unten ankommen, kann man den "else"-Teil weglassen.
- Und wenn nur noch "y" möglich ist, auch eine Prüfung, ob es "y" ist.
- Einfache Variablen würde ich klein schreiben.
- Konstanten ("$Archive") würde ich nach oben tun und insgesamt groß schreiben.
- 4 Zeichen Einrückung pro Block sind nicht verkehrt.

- Bei bash bin ich nie sicher, was in Arrays ankommt. Deshalb bevorzuge ich Perl (oder Python), weil das da wie erwartet funktioniert. Macht einfach mehr Spaß. Hier Perl:
Code:
#!/usr/bin/perl

use warnings;
use strict;

my $ARCHIVEFILE = "packed.zip";

#Nutzereingabe für Alter der Dateien
print "How old should the files be? ";
# User-Input einlesen geht in Perl so:
my $number_days = <>;
chomp($number_days);
if ($number_days =~ /[^0-9]/) {
    print "Error, only enter a number please!\n";
    exit 1;
}

# Output eines Shell-Befehls in ein Perl-Array einlesen:
my @files = `find -mtime +$number_days`;
# chomp entfernt \n-Zeichen am Ende aller Zeilen:
chomp @files;
my $i;
for $i (@files) {
    print "$i\n";
}
my $counter = 0;
my $file;
my $decision;
foreach $file (@files){
    print "Do you want to archive <$file>?(y/n): ";
    $decision = <>;
    chomp($decision);
    if ($decision eq "q") {
        print "Aborting.\n";
        last;
    }
    if ($decision ne "y" && $decision ne "n") {
        print "No proper Input recognized! Please only enter y or n!\n";
        next;
    }
    if ($decision eq "n") {
        print "skipped current Fie!\n";
        next;
    }
    print "File will be archived, deleting the original one!\n";
    system("zip \"$ARCHIVEFILE\" \"$file\"");
    $counter++; #Inkrementierung Counter für zählen der Dateien!
    # unlink($file);
}

#Bestätigung am Ende
print "\n$counter File(s), older then $number_days were successfully put in the <$ARCHIVEFILE>\n\n";

Die "unlink" (= "rm") - Zeile habe ich aus Sicherheitsgründen auskommentiert, sie müßte erst "scharfgestellt" werden.

Ich verlasse gern Schleifen mit break und continue (in Perl heißt das last / next), wenn Bedingungen erfüllt sind. Dadurch habe ich meist nur "if" in den Schleifen, selten "elif/elsif".
Ich weiß, daß Professoren das nicht gern sehen.
Offenbar sind break und continue erst später (1981?) in Computersprachen eingefügt worden.
Ich denke, es gibt sie lange genug, so daß man sie ruhig benutzen kann.
 
OP
H

Hk95

Newbie
erstmal vielen dank für deine Hilfestellung @abgdf
Python bevorzuge ich auf jedenfall auch, von Perl hab ich noch keine Ahnung, jedoch ist Bash ein Lernziel aus meinem Studium deswegen komm ich da mit dem Lernen nicht dran vorbei!

Ich konnte ein paar deiner Tipps anwenden und auch nachvollziehen was ich falsch gemacht habe! Im nachhinein waren sehr viele unnötige Fehler meiner Seite aus dabei!

Ich hab noch eine Frage bezüglich dem find bei Zeile 12. Ist das so korrekt geschrieben? Mein plan ist es Dateien die älter sind als x Tage auszugeben, jedoch wird mir mit echo $Files nichts ausgegeben. Wo genau liegt da der Fehler? Hab ich mich da wieder in der Syntax vertan?
 

abgdf

Guru
Hk95 schrieb:
Ich hab noch eine Frage bezüglich dem find bei Zeile 12. Ist das so korrekt geschrieben? Mein plan ist es Dateien die älter sind als x Tage auszugeben, jedoch wird mir mit echo $Files nichts ausgegeben. Wo genau liegt da der Fehler? Hab ich mich da wieder in der Syntax vertan?
Das dürfte das Problem mit den Arrays in bash sein, das ich angesprochen hatte.
Hilft es, diese Zeile davorzustellen?
Code:
IFS=$'\n'
Hk95 schrieb:
Python bevorzuge ich auf jedenfall auch, von Perl hab ich noch keine Ahnung
Wenn Du Python kennst und bash, sollte es eigentlich kein Problem sein, auch den Perl-Code zu lesen. Ist ja immer dasselbe: Variablen, Schleifen, Bedingungen ...
Die Dinge, die in Perl spezifische Syntax haben wie Lesen des Outputs eines Shell-Befehls hatte ich ja im Code kommentiert.
 
OP
H

Hk95

Newbie
danke Klara, hat auf jedenfall funktioniert und ich versteh jetzt auch warum!
Meine letzte Verständnislücke ist bei Zeile 45. Anstatt dass es durch die einzelnen dateien geht die in der Variable gespeichert sind, werden alle auf einmal ausgegeben und erst dann kommt die abfrage ob ich es archivieren will.

Wo bau ich denn die nächste Schleife ein um mir die Dateien einzeln abzuprüfen? oder fehlt mir da irgendwo ein break bzw continue?
 
OP
H

Hk95

Newbie
und auch danke an dich abgdf, von pearl hab ich noch nicht viel syntax gelesen aber ich kann es relativ verstehen, ich hab gesehen dass du in der schleife die option rauslässt wenn $Decision = y ist und es außerhalb der if schleife implementiert hast! Kannst du mir erklären warum genau und nicht direkt in der schleife? Oder ist das genau der Grund warum es bei mir nicht klappt gerade?

LG Hans! :)
 

abgdf

Guru
Hk95 schrieb:
und auch danke an dich abgdf, von pearl hab ich noch nicht viel syntax gelesen aber ich kann es relativ verstehen, ich hab gesehen dass du in der schleife die option rauslässt wenn $Decision = y ist und es außerhalb der if schleife implementiert hast! Kannst du mir erklären warum genau und nicht direkt in der schleife? Oder ist das genau der Grund warum es bei mir nicht klappt gerade?
Erstmal den Klassiker:

http://if-schleife.de/

:D

Dann ist man in der Perl-Community recht eigen damit, daß die Sprache "Perl" heißt, was groß geschrieben wird, im Gegenatz zu dem damit verbundenen Befehl "perl", der klein geschrieben wird. :)

Bei den Bedingungen wird ja zuerst geprüft, ob es was Anderes ist als "y" oder "n". Dann wird "n" geprüft. Liegen diese Fälle vor, wird die Schleife vorzeitig abgebrochen. Daher ist am Ende klar, daß nur noch "y" übrig bleibt. Das muß man deshalb dann nicht mehr überprüfen.
In der Schleife (foreach) sind die Befehle, die auf "y" folgen sollen, aber schon.
 
OP
H

Hk95

Newbie
Verstehe! Da brauch ich das "y" ja auch gar nicht mehr prüfen! Ich hab es jetzt einfach hinter die If-Abfragen geschrieben jedoch meckert er jetzt rum bei dem "done" für das abschließen der for-schleife, desweiteren hat es nicht geholfen die Dateien in $Files einzeln auszugeben, sodass ich sie je einzeln prüfen kann

Ich schick hier nochmal den Code!

Code:
#!/bin/bash

#Nutzereingabe für Alter der Dateien
echo "How old should the files be?"
read Number_days

if ! [[ "$Number_days" =~ [0-9]+$ ]];then
        echo "Error, only enter a number please!"
        exit 1
fi

#Mindestalter der Dateien filtern und ausgeben
IFS=$'\n'
Files=$(find ../hellow -maxdepth 1 -mtime +$Number_days)
echo $Files

#Durchgehen der Dateien
Archive="packed.zip"
Counter=0

for File in $Files;do
        echo -n "Do you want to archive <$Files>?(y/n):"
        read Decision

        if [ "$Decision" = "q" ];then
                echo -e "Aborting.\n"
                exit 2

        if [ "$Decision" != "y" ] && [ "$Decision" != "n" ]; then
                echo -e "No proper Input recognized! Please only enter y or n!\a"
                continue

        elif [ "$Decision" = "n" ]; then
                echo -e "skipped current Fie!\a"
                continue

        fi

        echo "File will be archived, deleting the original one!"
        zip "$Archive" $File
        let Counter++
        rm -v $File

done

#Bestätigung am Ende
echo "$Counter File(s), older then $number_days were successfully put in the <$Archive>"

exit 0
 
OP
H

Hk95

Newbie
Habe den Fehler gerade selbst noch gefunden! War nur ein Tippfehler bei der Variable $File!
Ich bin nun in der Lage jede Datei einzeln abzufragen, jedoch komm ich aus der Abfrage nicht raus wenn ich y, n oder q drücke! Und die jeweiligen Echo unter den If Bedingungen werden auch nicht ausgegeben! Liegt es daran dass ich continue bzw die exits falsch verwendet habe?
 

josef-wien

Ultimate Guru
Nach exit 2 fehlt fi, d. h. die Schleife ist danach immer zu Ende. Über das, was ansonsten in der Schleife passiert, solltest Du noch einmal nachdenken.

P. S. Ich würde zur Verarbeitung von $Decision case verwenden.
_______

Nachtrag: Mit einer überarbeiteten Schleife geht es bei https://linux-club.de/forum/viewtopic.php?f=91&t=123354 weiter.
 
Oben