Ihre Ergebnisse sind variabel.

Ihre Ergebnisse sind variabel.

$ sh Backup-zu-s3.sh

backup-to-s3.sh: 11: [: bkup_20151106_150532.zip: unexpected operator
backup-to-s3.sh: 11: [: bkup_20151106_150532.zip: unexpected operator
backup-to-s3.sh: 11: [: bkup_20151106_150532.zip: unexpected operator
backup-to-s3.sh: 11: [: bkup_20151106_150532.zip: unexpected operator
backup-to-s3.sh: 11: [: bkup_20151106_150532.zip: unexpected operator
backup-to-s3.sh: 11: [: bkup_20151106_150532.zip: unexpected operator

ubuntu@accretive-staging-32gb-ephemeral:~$ cat Backup-to-s3.sh

#Script to move /home/ubuntu/backup folder  to S3://auto-backup
#Author Ashish Karpe
cd /mnt/backup
filename="bkup_$(date +%Y%m%d_)"
/bin/ls -alF | awk '{ print $9 }'  > /tmp/file

for i in $(cat /tmp/file); do
#       echo $i;
#       read a;
#       echo $filename;
        if [ $filename* = $i ]
        then
                echo "Copying " $i "to S3://auto-backup";
                s3cmd put $i s3://auto-backup

            fi

done

Antwort1

  1. nicht verwenden, forum über die Zeilen einer Datei zu iterieren, verwenden

    while IFS= read -r line; do ...; done < filename
    
  2. Sie müssen lsdie Ausgabe überhaupt nicht in eine Datei umleiten,besondersmit-F

  3. Verwenden Sie Bash [[ x == y ]]für Mustervergleiche. Das Muster befindet sich auf der rechten Seite:
#!/bin/bash
cd /mnt/backup
prefix="bkup_$(date +%Y%m%d_)"

for file in * .*; do
    [[ -f $file ]] || continue    # skip things like directories and soft links
    if [[ $file == $prefix* ]]; then
        echo "Copying " $file "to S3://auto-backup";
        s3cmd put $file s3://auto-backup
    fi
done < /tmp/file

Antwort2

Auch wenn Sie die Ausgabe von „ls“ in eine Datei schreiben und diese analysieren, analysieren Sie indirekt die Ausgabe von „ls“, was entweder problematisch, eine wirklich schlechte Idee oder FALSCH!!! ist, je nachdem, wen Sie fragen.

Hier istwarum Sie die Ausgabe von 'ls' nicht analysieren sollten!

Hier istDateinamen und Pfadnamen in der Shell: So geht’s richtig!

Wenn beispielsweise eine der Dateien ein '-' (Bindestrich/Bindestrich) im Dateinamen hat, das nicht maskiert ist (durch vorangestellten Backslash ('\')), könnte es als Parameter interpretiert werden.

Das Parsen von „ls“ kann ganz einfach vermieden werden:

find . -maxdepth 1 -iname "*"
.
./dont_parse_ls.sh
./array.dat
./.bashrc
./BASH.Indirect.Reference.sh
./basharray.sh
./.forever

Das kommt auf das gleiche heraus wie

/bin/ls -alF | awk '{ print $9 }'

./
../
.bashrc
.forever/
BASH.Indirect.Reference.sh
array.dat
basharray.sh*
dont_parse_ls.sh

Ihre Ergebnisse sind variabel.

Antwort3

Das Skript weist mindestens zwei Hauptprobleme auf. Ihr grundlegendes Problem ist der Ausschnitt:

if [ $filename* =

Dies bringt einige Probleme mit sich. Erstens können Sie in Shell-Skripten kein Übereinstimmungsmuster „globben“. Das können Sie, aber wenn das Fileglob mehr als eine Übereinstimmung ergibt, erhalten Sie beide. In diesem Fall versucht das „[“-Programm (ja, es ist ein Programm), Folgendes auszuwerten:

filename1 filename2 filename3 = $i

Es funktioniert genau dann, wenn der Fileglob zu genau einem Dateinamen erweitert wird, und das können Sie selten garantieren. In Ihrem Fall wird $filename zu mindestens einer Datei erweitert, aber Sie sollten sich bewusst sein, dass dies nicht immer der Fall ist. Wenn „$file*“ zu gar keiner Datei erweitert wird, erhalten Sie möglicherweise (abhängig von einer Shopt-Einstellung) die leere Zeichenfolge:

= $i

was zum Scheitern führt [. Mit dem richtigen Shopt erhalten Sie jedoch stattdessen:

backup-2014-whatever* = $i

Mit dem *Teil des Vergleichs sein.

Das zweite grundlegende Problem ist die Verwendung des -FParameters in ls. Dadurch wird ls angewiesen, an den Dateinamen eines von mehreren Zeichen anzuhängen, je nachdem, ob es sich bei der Datei um eine ausführbare Datei, einen Softlink usw. handelt.

NetScr1be ist da auf der richtigen Spur, aber Sie müssen nicht NetScr1bes Rat befolgen und niemals verwenden ls... verwenden Sie einfach nicht ls -l. Verwenden Sie stattdessen , ls -1wodurch nur die Namen der Dateien in einer einzigen Spalte ohne Schnickschnack gedruckt werden. (Bei sehr großen Verzeichnissen werden sie sortiert, und das kann ein Problem sein. In diesem Fall gibt es eine Option ohne Sortierung; oder verwenden Sie find.)

Zur Erhöhung der Sicherheit sollten Ihre Variablen in doppelte Anführungszeichen gesetzt werden und sowohl LHS als auch RHS sollten mit einem Blindzeichen beginnen, um sicherzustellen, dass seltsame Dateinamen, die mit einem beginnen, -nicht durcheinander geraten.

Ich würde mehr oder weniger Glenns Rat befolgen und es folgendermaßen machen:

command ls -1 | while read file; do
    if [ x"$file" = x"$filename" ]]; then 
        echo Do Work Here
    fi
done

So bin ichwürdetu es, aber Glenn hat mir freundlicherweise mitgeteilt, ich sollte es wirklich tunseinWeg:

for file in *; do 
    if [[ $file == $filename ]]; then ...

Antwort4

Dieses Skript erledigt alles. Warum nicht das? Die Shell wählt die richtigen Dateien für Sie aus, Sie müssen also nicht Folgendes aufrufen ls:

#!/bin/sh
for file in /mnt/backup/bkup_$(date +%Y%m%d)_*
do
    s3cmd put "$file" s3://auto-backup
done
  • Der einzige externe Befehl ist s3cmd.
  • Keine ifAussagen.
  • Der einzige Entscheidungspunkt ist die forSchleife.
  • Leicht zu lesen.

verwandte Informationen