sh macht mich irre

soul_rebel

ist immer auf der flucht
mannomann... die sh raubt mir wieder die nerven....
ich habe hier ein backup-script geschrieben, das snychronisiert dir1 nach dir2 und guckt dann was in dir2 drin ist, was aber nicht in dir1 drin ist (unbenannte oder gelöschte dateien) und verschiebt diese nach dir3....
die erste aktion mache ich mit einem "einfachen" rsync aufruf, für die zweite lasse ich ein rsync "rückwärts" laufen wobei die option --dry-run verwendet wird, so dass die liste der dateien nur ausgegeben wird.
dann will ich durch die liste iterieren und die dateien verschieben, das geht aber nicht :(
die passage sieht so aus:
Code:
echo "** Beginning Update..."
  rsync --verbose --archive --executability --times --progress \
  --human-readable --one-file-system "$SRC" "$DEST"
  echo "** Done. Now moving (re)moved files to $MOV..."
  LIST=`rsync -v -a --dry-run "$DEST" "$SRC" | grep -v "bytes/sec" \
  | grep -v "building file list" | grep -v "total size is" | sed '/ /s//\\ /g'`
	
  for i in $LIST; do
	echo "$DEST/$i"
  	if [ -f "$DEST"/"$i" ]
  	then
  		mv -v "$DEST"/"$i" "$MOV"
  		#echo "$i"
  	fi
  done
  echo "** Done."
fi
leider werden trotz dem sed die leerzeichen nicht durch "\ " ersetzt, bzw. sie werden es doch aber verschwinden bei der ausgabe, bzw. dateinamen mit leerzeichen drin werden auf jeden fall in unterschiedliche listenelemente gesteckt.
wenn ich um $LIST anführungszeichen mache, dann ist die ausgabe auf der konsole (durch echo in der ersten zeile des loops) korrekt, also der dateiname mit leerzeichen wird in einer zeile ausgegeben. dafür wird der dateipfad nicht von der if-abfrage erkannt.
außerdem fehlt bei allen listenelementen nach dem ersten aus irgendeinem grund dann $DIST/ vor den listenelemente :confused:

aber vielleicht habe ich ja auch nur mal wieder die sh-syntax voll verplant (komme irgendwie nie darauf klar wann wo klammern und anführungszeichen drum müssen, wer wann wo mit leerzeichen klarkommt usw usf)

vielen dank für hilfe
 
Warum einfach wenn es auch kompliziert geht?

Code:
rsync -avqn "$DEST" "$SRC" | while read filepath
do
    # action with "$filepath"
done
 
Zuletzt bearbeitet von einem Moderator:
danke!

also ohne -q klappt das sehr gut (das greppen brauch ich trotzdem noch um die zeilen drüber und drunter wegzukriegen).
falls es jemand interessiert:
Code:
  echo "** Beginning Update..."
  rsync --verbose --archive --executability --times --progress \
  --human-readable --one-file-system "$SRC" "$DEST"
  echo "** Done. Now moving (re)moved files to $MOV..."
  rsync -v -a --dry-run --one-file-system "$DEST" "$SRC" \
  | grep -v "bytes/sec" | grep -v "building file list" \
  | grep -v "total size is" | while read filepath
  do
 	if [ -f "$DEST"/"$filepath" ]; then
	  mv -v "$DEST"/"$filepath" "$MOV"
  	elif [ -d "$DEST"/"$filepath" ]; then
  	  rmdir "$DEST"/"$filepath"
  	fi		
  done
  echo "** Done."

da sieht man mal wieder wie wenig plan ich von sh habe... egal wieviel ich dazu lese, sie erschließt sich mir nie ganz...

naja jetzt klappts ja :)
 
Na ja eigentlich ist das nicht so schwer. for geht die ihm übergebene Parameter(Liste) durch, diese müssen wie üblich durch Whitespace getrennt sein (dazu gehören auch Zeilenumbrüche).

Um mehrere Parameter zu einem zusammen zu fasen müssen die Strings in Anführungszeichen gesetzt werden. Auch das kennt man natürlich.

Somit geht for alle Wörter durch, da es jedes einzelne als ein Parameter sieht, setzt du darum Anführungszeichen, dann sieht es die ganze Liste als ein Parameter und wird genau einmal durchlaufen (Aufpassen musst man hier noch mit STDOUT und STDERR).

Sprich mit for kommen wir nicht weiter wenn Du an einzelne Zeilen willst die Leereuchen beinhalten könnten. Daher brauche wir dort "read" um Zeilenweise zu lesen.

Was dein Grep-Konstruktion angeht, so ist diese eigentlich unnötig da rsync mit -vq eigentlich nur die Liste ohne weitere Statistik und weitere Infos ausgibt.

Aron
 
hmm du hast aber schon die anderen parameter von Dir zu gesetzt?

Code:
> sh -c 'rsync -avqn a/ b/ | while read filepath; do echo "> $filepath"; done'
> ./
> a
> b
> c
 
Vielleicht hilft dir ja folgendes weiter.

Aus sh(1):
Code:
     IFS       Input Field Separators.  This is normally set to <space>,
               <tab>, and <newline>.  See the White Space Splitting section
               for more details.

Um Leerzeichen zu erhalten verwende ich ein Newline als Trennzeichen:
Code:
IFS="
"
 
@rosa: jo hab alles gesetzt, aber bei mir ist die liste komplett leer wenn -q dabei ist...

@kamikaze: hm das wäre auch eine möglichkeit... glaube ich hatte das letztes mal (bevor die serverplatte das zeitliche gesegnet hat) auch so gemacht...

naja jetzt tuts ja seinen zweck :)
 
Zurück
Oben