Al intentar obtener un archivo, ¿no le gustaría un error que diga que el archivo no existe para que sepa qué solucionar?
Por ejemplo, nvm recomienda agregar esto a su perfil / rc:
export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" # This loads nvm
Con lo anterior, si nvm.sh
no existe, obtendrá un "error silencioso". Pero si lo intentas . "$NVM_DIR/nvm.sh"
, la salida será FILE_PATH: No such file or directory
.
shell-script
JBallin
fuente
fuente
HOME
.Respuestas:
En los shells POSIX,
.
es un componente integrado especial, por lo que su falla hace que el shell salga (en algunos shells comobash
, solo se hace cuando está en modo POSIX).Lo que califica como error depende del shell. No todos salen con un error de sintaxis al analizar el archivo, pero la mayoría se cierra cuando no se puede encontrar o abrir el archivo de origen. No conozco ninguno que salga si el último comando en el archivo de origen regresa con un estado de salida distinto de cero (a menos que la
errexit
opción esté activada, por supuesto).Aquí haciendo:
Es un caso en el que desea obtener el archivo si está allí, y no si no está (o está vacío aquí con
-s
).Es decir, no debe considerarse un error (error grave en shells POSIX) si el archivo no está allí, ese archivo se considera un archivo opcional.
Seguiría siendo un error (fatal) si el archivo no fuera legible o si fuera un directorio o (en algunos shells) si hubiera un error de sintaxis al analizarlo, que serían condiciones de error reales que deberían informarse.
Algunos dirían que hay una condición de carrera. Pero lo único que significa sería que el shell saldría con un error si el archivo se elimina entre el
[
y.
, pero diría que es válido considerar que es un error que este archivo de ruta fija desaparezca repentinamente mientras el script está corriendo.Por otra parte,
donde
command
¹ elimina el atributo especial del.
comando (para que no salga del shell por error) no funcionaría como:.
los errores pero también los errores de los comandos ejecutados en el archivo de origenOtras sintaxis comunes (consulte, por ejemplo,
grep -r /etc/default /etc/init*
en los sistemas Debian para las secuencias de comandos de inicio que aún no se han convertidosystemd
(dondeEnvironmentFile=-/etc/default/service
se utiliza para especificar un archivo de entorno opcional)) incluyen:[ -e "$file" ] && . "$file"
Verifique que el archivo esté allí, aún consígalo si está vacío. Sigue siendo un error grave si no se puede abrir (aunque esté allí o estaba allí). Es posible que vea más variantes como
[ -f "$file" ]
(existe y es un archivo normal ),[ -r "$file" ]
(es legible) o combinaciones de ellas.[ ! -e "$file" ] || . "$file"
Una versión un poco mejor. Deja en claro que el archivo que no existe es un caso correcto. Eso también significa
$?
que reflejará el estado de salida del último comando ejecutado$file
(en el caso anterior, si obtiene1
, no sabe si es porque$file
no existió o si ese comando falló).command . "$file"
Espere que el archivo esté allí, pero no salga si no se puede interpretar.
[ ! -e "$file" ] || command . "$file"
Combinación de lo anterior: está bien si el archivo no está allí, y para shells POSIX, las fallas para abrir (o analizar) el archivo se informan pero no son fatales (lo que puede ser más deseable
~/.profile
).¹ Nota:
zsh
Sin embargo, no se puede usarcommand
así a menos que en lash
emulación; tenga en cuenta que en el shell Korn, ensource
realidad es un alias paracommand .
, una variante no especial de.
fuente
.bash_profile
. Supongo que es mejor prevenir que curar, pero ¿bash alguna vez está en modo POSIX cuando.bash_profile
se obtiene?bash
cuando no está en modo POSIX. Desearía[ -e /file ] && . /file
si no lo considera un error cuando el archivo no existe. La fuente de prueba maneja el error, si no se puede hacer aquí..
ya informará un error (en stderr). Y si la intención es no considerarlo un error cuando el archivo no existe, eso no es correcto (y no es posible, desde el estado de salida, decir si.
falló porque el archivo no existía o no era legible, o era no analizable, o el último comando falló), que son los puntos que estoy haciendo aquí en esta respuesta.Mantenedor de
nvm
la respuesta de:Mi interpretación (combinada con la excelente explicación de Stéphane y el comentario de Kusalananda):
Es más simple y seguro.
Se defiende contra los shells POSIX que salen al inicio debido a la falta de un archivo (por varias razones). Aquellos que usan shells que no son POSIX (por ejemplo, bash) pueden eliminar el condicional si así lo prefieren.
fuente
/etc
, entonces permite que algunos usuarios tengan el archivo y otros no. En mi humilde opinión, lanvm
respuesta del mantenedor solo toca un aspecto.Como JBallin y Stéphane Chazelas han señalado, en shells POSIX, el abastecimiento de un archivo que no existe provocaría un error al iniciar sesión.
Pero agregar una prueba para ver si el archivo existe y luego intentar obtenerlo puede causar algo llamado condición de carrera. Si algo cambia
nvm.sh
entre el[ -s nvm.sh ]
y el. nvm.sh
, causará exactamente el error que están tratando de prevenir, aunque con mucha menos frecuencia.En general, la forma de prevenir las condiciones de carrera es simplemente intentar lo que desea hacer, luego manejar el error si falla, por ejemplo
Resulta que esto no funciona en los shells POSIX, porque, como se indicó anteriormente, la
.
falla hará que el shell salga inmediatamente, antes de que se pueda ejecutar cualquier manejo de errores.Mi respuesta argumenta que los shells POSIX no son relevantes para esta pregunta, porque
.bash_profile
nunca deberían ejecutarse en modo POSIX. Entonces podemos hacer el código anterior de todos modos.Para estar más seguros, podríamos asegurarnos de que el modo POSIX no esté vigente, o asegurarnos de que el modo POSIX esté deshabilitado utilizando la técnica descrita en /unix//a/383581/3169 .
La respuesta de Stéphane tiene algunas sugerencias útiles sobre cómo manejar todos los shells POSIX, lo que creo que fue la intención del autor nvm, pero fue sutilmente diferente de lo que estaba haciendo la pregunta aquí, y es por eso que tenemos múltiples enfoques posibles, dependiendo de cuál sea su objetivo. .
fuente