8 Stimmen

Skript-Datei vs. Befehlszeile: rsync und --exclude

Ich habe ein einfaches Test-Bash-Skript, das so aussieht:

#!/bin/bash

cmd="rsync -rv --exclude '*~' ./dir ./new"
$cmd # execute command

Wenn ich das Skript ausführe, kopiert es auch die Dateien, die mit einem ~ auch wenn ich sie eigentlich ausschließen wollte. Wenn ich denselben rsync-Befehl direkt von der Befehlszeile aus ausführe, funktioniert er! Weiß jemand, warum und wie man das Bash-Skript zum Laufen bringt?

Übrigens, ich weiß, dass ich auch mit --exclude-from aber ich möchte trotzdem wissen, wie das funktioniert.

6voto

Dennis Williamson Punkte 322329

Versuchen Sie eval :

#!/bin/bash

cmd="rsync -rv --exclude '*~' ./dir ./new"
eval $cmd # execute command

5voto

Gordon Davisson Punkte 105638

Das Problem ist nicht, dass Sie den Befehl in einem Skript ausführen, sondern dass Sie den Befehl in eine Variable einfügen und dann die erweiterte Variable ausführen. Und da die Variablenexpansion erfolgt, nachdem die Anführungszeichen bereits entfernt wurden, werden die einfachen Anführungszeichen um das Ausschlussmuster nie entfernt... und so schließt rsync Dateien aus, deren Namen mit ' beginnen und mit ~' enden. Um dies zu beheben, entfernen Sie einfach die Anführungszeichen um das Muster (das Ganze steht bereits in doppelten Anführungszeichen, sie werden also nicht benötigt):

#!/bin/bash

cmd="rsync -rv --exclude *~ ./dir ./new"
$cmd # execute command

...apropos, warum geben Sie den Befehl in eine Variable ein, bevor Sie ihn ausführen? Im Allgemeinen ist dies ein guter Weg, um den Code verwirrender zu machen, als er sein muss, und um seltsame Parsing-Fehler auszulösen (einige sind sogar noch seltsamer als dieser). Wie wäre es also mit:

#!/bin/bash

rsync -rv --exclude '*~' ./dir ./new

0 Stimmen

Ich habe sie in eine Variable zur Fehlersuche eingegeben. Ich habe ohne einfache Anführungszeichen angefangen und das war sogar noch schlimmer (eigentlich habe ich sie deshalb dort hineingeschrieben), weil sie sich ausdehnten. Z.B. "rsync -r --exclude *~ ./dir ./new" erweitert zu "rsync -r --exclude foo~ bar~ foobar.sh~ ./dir ./new"

0 Stimmen

Haben Sie es mit den einfachen Anführungszeichen versucht, aber ohne sie in eine Variable zu setzen (wie in meiner zweiten Empfehlung)? Es sollte gut funktionieren (und schien es auch, als ich es getestet habe).

0voto

Zsolt Botykai Punkte 48177

Sie können eine einfache --eclude '~' as (gemäß der Manpage):

  • Wenn das Muster mit einem / beginnt, ist es an einer bestimmten Stelle in Hierarchie der Dateien verankert, andernfalls wird es mit dem Ende des Pfadnamens. Dies ist ähnlich wie ein führendes ^ in regulären Ausdrücken. Somit würde "/foo" auf einen Namen "foo" entweder im der "Wurzel der Übertragung" (für eine globalen Regel) oder im Verzeichnis der Merge-Datei Verzeichnis (bei einer Regel pro Verzeichnis). Ein unqualifiziertes "foo" würde mit einem Namen "foo" irgendwo in der Baumstruktur denn der Algorithmus wird rekursiv rekursiv von oben nach unten angewendet wird; er verhält sich so, als ob jede Pfadkomponente das Ende des Dateinamens zu sein. Dateinamens zu sein. Sogar das unverankerte "sub/foo" würde an jedem Punkt in der Hierarchie übereinstimmen, wo ein "foo" innerhalb eines Verzeichnisses namens "sub" gefunden wurde. Siehe den Abschnitt über ANCHORING INCLUDE/EXCLUDE-MUSTERN für eine vollständige Diskussion, wie man ein Muster angibt das auf die Wurzel des Übertragung passt.
  • wenn das Muster mit einem / endet, wird es nur mit einem Verzeichnis übereinstimmen, nicht mit einem reguläre Datei, einen Symlink oder ein Gerät.
  • rsync wählt zwischen einem einfachen String-Match und einem Wildcard-Match indem es prüft, ob das Muster eines der folgenden drei Platzhalterzeichen enthält Zeichen enthält: "*", "?" und "[" .
  • ein '*' passt auf jede Pfadkomponente, hört aber bei Schrägstrichen auf.
  • verwenden Sie '**', um alles zu finden, einschließlich Schrägstriche.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X