Einfaches Bash-Skript funktioniert nicht

Einfaches Bash-Skript funktioniert nicht

Dieses Skript sollte alle Dateien, deren Namen als Argumente in der Befehlszeile angegeben sind, in das Stammverzeichnis des Benutzers kopieren. Wenn keine Dateien angegeben wurden, sollte das Skript read verwenden, um nach Dateinamen zu fragen, und alle in der Antwort angegebenen Dateinamen in das Stammverzeichnis des Benutzers kopieren.

if [ -z $1 ]
then
    echo provide filenames
    read $FILENAMES
else
    FILENAMES="$@"
fi

echo the following filenames have been provided: $FILENAMES
for i in $FILENAMES
do
    cp $i $HOME
done

Wenn ich Argumente als Zeichenfolge angebe, funktioniert es. Aber wenn ich „read $FILENAMES“ angebe, funktioniert es nicht.

Der Mentor zeigt in seinen Lektionen dieselbe Lösung, aber nicht, wie sie funktioniert. Bildbeschreibung hier eingeben

UPDATE Nachdem ich die Dateinamen als Argumente eingegeben habe, werden leere Zeichenfolgen ausgegeben und die Dateien werden nicht an den Speicherort $HOME kopiert

[dmytro@oc1726036122 ~]$ cd Desktop/
[dmytro@oc1726036122 Desktop]$ . totmp 
provide filenames
one two
the following filenames have been provided:
the following filenames have been provided:
[dmytro@oc1726036122 Desktop]$

Antwort1

Das readdeklariert Variablen, anstatt sie zu lesen. Einfach ausgedrückt: Entfernen Sie das $von readund schon kann es losgehen.

if [ -z $1 ]
then
    echo provide filenames
    read FILENAMES
else
    FILENAMES="$@"
fi

echo the following filenames have been provided: $FILENAMES
for i in $FILENAMES
do
    cp $i $HOME
done

BEARBEITEN: Ich sehe, dass Sie den Befehl source( .) verwenden, um ein Skript auszuführen.

[dmytro@oc1726036122 Desktop]$ . totmp

Für dieses spezielle Skript mag das in Ordnung sein, aber tun Sie das niemals für komplexe Skripte. Andernfalls würden Sie eine Variable oder Funktion aus diesem Skript in Ihre Shell einspeisen. Verwenden Sie einfachbash totmp

Antwort2

Das Problem, das Sie zu blockieren scheint, ist, dass der readBefehl falsch ist. Das ihm übergebene Argument sollte ein Variablenname sein und daher ohne ein übergeben werden $(das erweitert den Inhalt der Variablen, der zu diesem Zeitpunkt leer ist, sodass das Ergebnis ein ohne übergebene Variablennamen $ist .)read

read FILENAMES

Es gibt ein weiteres Problem bei der Prüfung auf das Fehlen des ersten Befehlszeilenarguments. Wenn es nicht vorhanden ist, $1wird then ins Nichts expandiert (nicht in eine leere Zeichenfolge), was zu Problemen mit dem [Befehl führen könnte, da [ -z ]es eigentlich nicht gültig sein sollte, [ -z "" ]was Sie in diesem Fall überprüfen würden. Kurz gesagt, Sie müssen diese Variable in Anführungszeichen setzen:

if [ -z "$1" ]

Da Sie Bash verwenden, können Sie auch verwenden [[ ... ]], was im Allgemeinen besser ist, da es sich um einen internen Befehl handelt (in diesem Fall sollte dieser Befehl ohne Anführungszeichen funktionieren, aber die Anführungszeichen beizubehalten schadet nicht und sieht gut aus.)

(PS: An diesem Skript ist noch so viel mehr falsch, es ist so weit von Best Practices entfernt, dass es mich wirklich entsetzt, wenn ich sehe, wie jemand so etwas lehrt. Leider scheint die Messlatte für das Unterrichten von Bash sehr niedrig zu sein, und die Handbücher sind sehr komplex, bis man es wirklich gut verstanden hat, also weiß ich auch nicht, ob ich eine bessere Empfehlung hätte, wie man es richtig lernt.)☹️

Antwort3

Der readBefehl übernimmt die Variable, aber Sie beziehen sich bereits auf die Werte der Variablen:

 #correct syntax
 read variable
 #wrong syntax
 read $variable

$variableist der Wert von variableund am Anfang des Skripts ist dieser nicht festgelegt/leer.

verwandte Informationen