Mein Skript:
#!/bin/sh
_directory1="/home/user/test1"
_directory2="test2"
cd "${_directory1}/$_directory2"
for i in *
do
echo "$i"
done
Und hier ist der Fehler:
./myscript.sh: 6: cd: can't cd to /home/user/test1/test2
Was mache ich falsch?
Antwort1
Ihr Originalcode vor den Änderungen:
#!/bin/sh
_directory1="~/test1"
_directory2="test2"
for i in $(cd "${_directory1}/$_directory2")
do
echo "$i"
done
Die Tilde (
~
) verhält sich nicht wie eine Variable. Sie wird beispielsweise nicht in den Pfad zu Ihrem Home-Verzeichnis erweitert, wenn sie in Anführungszeichen verwendet wird. Verwenden Sie in einem Skript$HOME
anstelle der Tilde.~
ist eine „Abkürzung“, die Sie möglicherweise in der Befehlszeile verwenden möchten, die$HOME
in einem Skript jedoch aussagekräftiger ist.- Sehen "Warum wird die Tilde (~) innerhalb von Anführungszeichen nicht erweitert?" für mehr Informationen.
cd
gibt nichts aus, das Sie durchlaufen können, daher bringt Ihnen die Verwendungcd
in einer Befehlsersetzungfor
nichts. Leider ist unklar, was Ihre Schleife eigentlich tun soll, daher kann ich Ihnen keine todsichere alternative Implementierung geben.
Der Code mit Ihren Änderungen:
#!/bin/sh
_directory1="/home/user/test1"
_directory2="test2"
cd "${_directory1}/$_directory2"
for i in *
do
echo "$i"
done
Dieser Code würde nur
"./myscript.sh: 6: cd: can't cd to /test2"
wenn Sie den Namen der Variablen falsch schreiben _directory1
(und die falsch geschriebene Variable leer ist und das /test2
Verzeichnis nicht existiert).
Anschließend haben Sie die Fehlermeldung bearbeitetwiederzu sagen, dass es ausgibt
./myscript.sh: 6: cd: can't cd to /home/user/test1/test2
was einfach bedeutet, dass das Verzeichnis /home/user/test1/test2
nicht existiert. Sie haben keinen Beweis dafür erbracht, dass dieses Verzeichnistutexistieren, also müssen wir uns diesbezüglich auf das Wort Ihres Systems verlassen.
Hier ist ein Skript, das den Inhalt eines Verzeichnisses auflistet (vorausgesetzt, das Verzeichnis existiert). Der Code druckt den vollständigen Pfadnamen jeder Datei.
#!/bin/bash
topdir=$HOME/test1
subdir=test2
printf '%s\n' "$topdir/$subdir"/*
Oder,
#!/bin/bash
topdir=$HOME/test1
subdir=test2
shopt -s nullglob
for name in "$topdir/$subdir"/*; do
printf '%s\n' "$name"
done
Die nullglob
Shell-Option bewirkt, dass die Schleife überhaupt nicht ausgeführt wird, wenn das angegebene Muster nicht übereinstimmt. Ohne die nullglob
Option würde das Muster unerweitert bleiben, wenn es nicht übereinstimmt, und die Schleife würde es in einer einzigen Iteration als Wert verwenden $name
.
Wenn Sie an versteckten Namen (Dateinamen, die mit einem Buchstaben beginnen) interessiert sind, können Sie auch die dotglob
Shell-Option ( ) festlegen .shopt -s dotglob
.
Oder, ohne den vollständigen Pfad zu jedem Dateinamen auszudrucken,
#!/bin/bash
topdir=$HOME/test1
subdir=test2
cd "$topdir/$subdir" || exit 1
printf '%s\n' *
exit 1
Wenn dies fehlschlägt, wird das Skript beendet cd
.
Oder,
#!/bin/bash
topdir=$HOME/test1
subdir=test2
cd "$topdir/$subdir" || exit 1
shopt -s nullglob
for name in *; do
printf '%s\n' "$name"
done
Um nur die Dateinamen ohne den vollständigen Pfad auszudrucken, ohne Folgendes zu verwenden cd
:
#!/bin/bash
topdir=$HOME/test1
subdir=test2
shopt -s nullglob
for name in "$topdir/$subdir"/*; do
printf '%s\n' "$( basename "$name" )"
# or: printf '%s\n' "${name##*/}"
done
Dies verwendet das basename
Dienstprogramm, um nur den Dateinamenteil der Pfadnamen zu extrahieren. Die Alternative im Kommentar verwendet eine Standardparametersubstitution, ${name##*/}
um den anfänglichen Verzeichnispfad vor den Dateinamen zu löschen (wörtlich „entfernen Sie die längste Präfixzeichenfolge, die dem Muster entspricht, */
aus $name
“).