Warum zeigt mein Bash-Skript den Fehler "zu viele Argumente" im Befehl "cp" an?

5337
Mike

Hier ist mein Skript, ich bekomme den Fehler "Zeile 33: [: zu viele Argumente", ich bin verwirrt warum, werden hier nur 2 Argumente zur Verfügung gestellt?

Ich füge dem Skript zwei Verzeichnisse ohne Leerzeichen hinzu, dh $ 1 = dir1 / und $ 2 = dir2 /

#!/bin/bash  ### Assign suitable names to arguements. ###  source=$1 dest=$2  ### Error handler for all script errors. ###  function errorHandler { case $1 in ERRargs) printf "USAGE: e2backup source_dir dest_dir.\n"; exit 1;; ERRsource) printf "ERROR: Source does not exist or is not a directory.\n"; exit 2;; ERRdest) printf "ERROR: Destination does not exist or is not a directory.\n"; exit 3;; ERRempty) printf "ERROR: Destination is not empty.\n"; exit 4;; esac }  ### Test num. of args, source/dest validity and empty dest. Then perform backup. ###  if [ $# -ne 2 ] then errorHandler ERRargs elif [ ! -d $source ] then errorHandler ERRsource elif [ ! -d $dest ] then errorHandler ERRdest elif [ -n "$(ls -A $dest)" ]  then errorHandler ERRempty elif [ cp -R $source $dest ] then printf "Successfully backed-up from $source to $dest"; exit else printf "Back-up failed, please see e2backup.error"; exit 5 fi 
0

2 Antworten auf die Frage

1
Alex P.

Es ist cpaber nicht [alias test, was den Fehler gibt

Und wie kann ich dieses Problem mildern? Ich möchte den return-Status für das elif verwenden, aber gleichzeitig die cp ausführen ... Mike vor 11 Jahren 0
Angenommen, Sie möchten diese Art von fehlerhafter Codierung beibehalten (meiner Meinung nach) ... Sie müssen den Rückkehrcode als Ausgabe ausgeben lassen: `elif $ (cp -R" $ source "" $ destination "; printf"% d " "$?"); dann` vor 11 Jahren 2
elif testet den Rückgabestatus des folgenden Befehls. Normalerweise lautet der Befehl "[", ein Alias ​​für "test". Wenn Sie den Rückkehrstatus von "cp" verzweigen möchten, schreiben Sie einfach "elif cp -R $ source $ dest". garyjohn vor 11 Jahren 2
+1 Gary, seine Version stimmt auch. Ich habe es mir gedacht, wo ich immer Befehle und Beendigungscodes von Tests trenne. vor 11 Jahren 0
Nizza ein Kerl. Und warum ist diese schlechte Codierung Ihrer Meinung nach? Irgendwelche Tipps wären dankbar. Mike vor 11 Jahren 0
Nun, es ist besser, Befehle getrennt von Tests auszuführen, sodass das Debuggen einfacher ist. Sie erfahren genau wie in Ihrem Beispiel, dass es sich nicht um ein cp-Problem handelt, sondern um ein if-Statement (dasselbe gilt für `ls -A $ dest`, das Sie dort haben); Außerdem können Sie sowohl den Exit-Code als auch die Ausgabe verwenden, sodass Sie die Ausgabe auch für das spätere Debugging ausdrucken können. Es ist auch gut, einen String-Parameter in doppelte Anführungszeichen zu setzen. Wenn Sie also ein Leerzeichen enthalten, wird bash nicht der Meinung sein, dass Sie mehrere Parameter anstelle von nur einem für diesen String haben. vor 11 Jahren 0
Auch wenn ich es mag, dass Sie printf und kein Echo verwenden, was nicht POSIX ist, verwenden Sie es nicht auf die bestmögliche Weise. Wenn in $ source und $ dest einige Sonderzeichen wie% vorhanden sind, versucht printf, es zu erweitern, da der erste Parameter für printf die Formatierungselemente wie% d,% s,% .2f erweitert. Daher ist es am besten, alle Variablen als separate Parameter des Drucks zu verwenden. In Ihrem Beispiel: `printf" Erfolgreich von '% s' auf '% s' gesichert. " "$ source" "$ dest" #Einfache Anführungszeichen dienen nur der Ästhetik, daher ist es einfacher zu wissen, wo der Wert endete vor 11 Jahren 0
OK, Süße, Prost Radoo. Mike vor 11 Jahren 0
Es ist auch nicht gerade eine schlechte Sache, dann in einer neuen Zeile zu sein, aber es bringt Ihnen keinen Vorteil, nur Zeilenumbrüche in Ihrem Code. Sie können einfach schreiben, wenn ...; dann` vor 11 Jahren 0
0
Huygens

To the point, the statement cp -R $source $dest is not a test condition in itself. So you should tell BASH to execute the cp commands. You can either use the back-quote or $(...) and test against the result or better as suggested by one commenter:

if [[ $# -ne 2 ]] then errorHandler ERRargs elif [[ ! -d $source ]] then errorHandler ERRsource elif [[ ! -d $dest ]] then errorHandler ERRdest elif [[ -n "$(ls -A $dest)" ]] then errorHandler ERRempty elif cp -R $source $dest then printf "Successfully backed-up from $source to $dest"; exit else printf "Back-up failed, please see e2backup.error"; exit 5 fi 

Updated: BASH supports both '[]' and '[[]]' for a test. There is a slightly different meaning that the curious one can find in the man page. In addition, one could also use other ways to do a test, like using the test bash builtin command.

Ihr Rückruf ist falsch. [] ist gleichbedeutend mit test. [[]] ist eine neue Mischung, die in bash eingeführt wurde, da ich mich an einige Version nicht erinnere. Dadurch wird die Testfunktionalität durch Pattern-Matching erweitert. Auch wenn es sich nicht um ein sehr nützliches Feature handelt, handelt es sich nicht um POSIX, was in manchen Fällen nicht wünschenswert ist, etwa wenn das Skript auf verschiedene Shells verteilt werden soll. vor 11 Jahren 0
Bei Radoo werde ich die Antwort danke korrigieren. Da dies jedoch ein Bash-Scrip ist (erste Zeile ist `#! / Bin / bash '), funktioniert' [[]] 'auf jeder Plattform, die Bash unterstützt. Selbst wenn ich versuchte, ein Skript so agnostisch für eine bestimmte Shell zu machen, habe ich es nie geschafft, es ohne Änderung von BASH bis KSH tragbar zu haben. Huygens vor 11 Jahren 0
Es gibt keinen Grund, die Standardausgabe von 'cp' zu erfassen, da diese normalerweise keine erzeugt. Wir verwenden nur elif cp -R "$ source" "$ dest" `, um den Exit-Status von` cp` zu testen. chepner vor 11 Jahren 0
@chepner Ich bin mir nicht sicher, was ich an diesem Tag gegessen habe, muss ziemlich schlecht gewesen sein ;-) Ich habe es noch einmal korrigiert und sogar diesen Beitrag zu einem Community-Wiki gemacht, da meine ursprüngliche Antwort ziemlich weit von dem entfernt ist, was der Strom dank Radoo und ist Sie! Huygens vor 11 Jahren 0