Mi guión:
#!/bin/sh
_directory1="/home/user/test1"
_directory2="test2"
cd "${_directory1}/$_directory2"
for i in *
do
echo "$i"
done
Y aquí está el error:
./myscript.sh: 6: cd: can't cd to /home/user/test1/test2
¿Qué estoy haciendo mal?
Respuesta1
Su código original antes de las ediciones:
#!/bin/sh
_directory1="~/test1"
_directory2="test2"
for i in $(cd "${_directory1}/$_directory2")
do
echo "$i"
done
La tilde (
~
) no se comporta como una variable. Por ejemplo, no se expandirá a la ruta de su directorio personal cuando se use entre comillas. En un guión, utilice$HOME
en lugar de tilde.~
es un "atajo" que quizás desee utilizar en la línea de comando, pero$HOME
es más descriptivo en un script.- Ver "¿Por qué la tilde (~) no se expande entre comillas dobles?" para más información.
cd
no genera nada que pueda recorrer, por lo que usarlocd
en una sustitución de comandofor
no le servirá de nada. Desafortunadamente, no está claro qué desea que haga realmente su bucle, por lo que no puedo ofrecerle una implementación alternativa segura.
El código con tus ediciones:
#!/bin/sh
_directory1="/home/user/test1"
_directory2="test2"
cd "${_directory1}/$_directory2"
for i in *
do
echo "$i"
done
Este código solo generaría
"./myscript.sh: 6: cd: can't cd to /test2"
si escribe mal el nombre de la variable _directory1
(y la variable mal escrita está vacía y el /test2
directorio no existe).
Luego editaste el mensaje de error.de nuevodecir que produce
./myscript.sh: 6: cd: can't cd to /home/user/test1/test2
lo que simplemente significa que el directorio /home/user/test1/test2
no existe. No ha dado pruebas de que este directoriohaceexisten, por lo que tenemos que confiar en la palabra de su sistema al respecto.
Aquí hay un script que enumera el contenido de un directorio (suponiendo que el directorio exista). El código imprime la ruta completa de cada archivo.
#!/bin/bash
topdir=$HOME/test1
subdir=test2
printf '%s\n' "$topdir/$subdir"/*
O,
#!/bin/bash
topdir=$HOME/test1
subdir=test2
shopt -s nullglob
for name in "$topdir/$subdir"/*; do
printf '%s\n' "$name"
done
La nullglob
opción Shell hace que el bucle no se ejecute en absoluto si el patrón dado no coincide con nada. Sin configurar la nullglob
opción, el patrón permanecería sin expandir si no coincidiera con nada, y el bucle lo usaría como valor $name
en una sola iteración.
También es posible que desee configurar la dotglob
opción de shell ( shopt -s dotglob
) si está interesado en nombres ocultos (nombres de archivos que comienzan con un .
carácter).
O, sin imprimir la ruta completa a cada nombre de archivo,
#!/bin/bash
topdir=$HOME/test1
subdir=test2
cd "$topdir/$subdir" || exit 1
printf '%s\n' *
Terminará exit 1
el script si cd
falla.
O,
#!/bin/bash
topdir=$HOME/test1
subdir=test2
cd "$topdir/$subdir" || exit 1
shopt -s nullglob
for name in *; do
printf '%s\n' "$name"
done
Para imprimir solo los nombres de archivos sin su ruta completa, sin usar 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
Esto utiliza la basename
utilidad para extraer solo la parte del nombre de archivo de las rutas. La alternativa en el comentario utiliza una sustitución de parámetro estándar, ${name##*/}
, para eliminar la ruta del directorio inicial antes de los nombres de archivo (literalmente "eliminar la cadena de prefijo más larga que coincida con el patrón */
de $name
").