0 votos

¿Cómo puedo escribir un shell script en Mac como puedo hacer en Windows?

Me gustaría escribir un conjunto de shell scripts que se ejecuten sin problemas en Mac sin tener en cuenta desde dónde se llaman.

Actualmente estoy luchando sobre cómo implementar esto.

En Windows, podría escribir tres secuencias de comandos scripts

A.bat en la carpeta A B.bat en la carpeta Subfolder que es una subcarpeta de A y qué camino es A/Subfolder C.bat en la carpeta Subfolder que es una subcarpeta de A y qué camino es A/Subfolder

En A.bat Podría escribir

call Subfolder/B.bat

en B.Bat Podría escribir

call C.bat

y ambos scripts A y B se ejecutaría con éxito.

En Mac, sin embargo, tengo que anteponer ./ a cada script para que sea reconocido como script.

Así que cuando escribo en a.sh código:

Subfolder/b.sh

y luego en b.sh código

./c.sh

cuando ejecute ./b.sh desde el terminal se ejecuta con éxito.

Sin embargo, cuando ejecuto ./a.sh desde una carpeta principal en el terminal, falla con el error

./a.sh
Subfolder/b.sh: line 1: ./c.sh: No such file or directory

¿Es posible en Mac escribir un código en b.sh que se ejecute sin tener en cuenta si se llama desde la carpeta actual o desde la carpeta padre?

1voto

Hay dos conceptos relevantes para entender lo que está pasando aquí:

  • cuando se ejecutan binarios o shell scripts como name-of-executable la cáscara mira en $PATH para la lista de directorios en los que se podría almacenar el binario/shell script. La primera coincidencia encontrada se utiliza para ejecutar el binario/script, si no se encuentra ninguna coincidencia se obtiene un mensaje de error. Si en cambio lo ejecuta como ./name-of-executable o /path/to/executable $PATH no se busca, sino que se toma la ruta relativa al directorio actual (si empieza por ./ o ../ ) o absoluta
  • cada proceso (incluyendo cada shell script) tiene un directorio por defecto en el que se ejecuta y que se hereda a cualquier proceso hijo iniciado

Así que en tu caso si ejecutas ./a.sh el directorio actual sigue siendo el a.sh se almacena en incluso cuando subfolder/b.sh se está ejecutando, lo que permite que ./c.sh fallar.

La forma más fácil de evitar esto es cambiar siempre de directorio antes de llamar a los procesos hijos (y por supuesto volver a cambiar después). Así que en a.sh escribirías

cd subfolder
./b.sh
cd ..

que permitiría b.sh para llamar ./c.sh dentro de la misma subcarpeta sin problemas.

1voto

Nate Puntos 220

Afirmo que hay tres conceptos relevantes con los que estás (/puedes estar) teniendo problemas aquí:

  • En un shell de estilo unix, cuando se utiliza un nombre de comando que no incluye un "/", se busca en los directorios del PATH variable de entorno (lugares como /bin, /usr/bin, etc), no cualquier lugar relativo a donde se encuentra (o algún script actual). Por otro lado, si contiene un "/", se trata como una ruta para que se ejecute el comando/script. Utilizando ./ delante de un nombre script es sólo una forma de especificar una ruta a un archivo en el directorio actual.

  • En unix (incluyendo MacOS), cuando se especifica una ruta relativa (a un documento, script, o lo que sea), se resuelve en relación con el directorio de trabajo actual del proceso; en un script, esto es generalmente no el directorio en el que está el script, sino el directorio en el que estaba el usuario (o lo que sea) cuando ejecutó el script.

    Así que si estás en /Users/patlatus y ejecutas un script en /Users/patlatus/Documents/scriptproject, y el script hace referencia a Subfolder/b.sh buscará /Users/patlatus/Subcarpeta/b.sh. Encontrar archivos relativos al script es complicado, y no siempre es posible (o incluso está bien definido), pero en bash normalmente se puede derivar de $BASH_SOURCE . Algo así:

    scriptdir=$(dirname "$BASH_SOURCE")    # Find the current script's directory
    "$scriptdir/Subfolder/b.sh"            # Run a script in a subdirectory of that
  • Cuando se ejecuta un script sólo con su ruta (o nombre), se ejecutará como un subproceso. Esto significa que hereda copias de cualquier variable exportada desde el script padre, pero no las variables no exportadas, y cualquier cambio que haga en las variables no se propagará al shell del script padre. Esto es diferente de cómo call funciona en un batch script; call está más cerca de ejecutar otro script con el source (o su sinónimo . ), que lo ejecuta en el mismo proceso del shell (con acceso total a las variables, etc.). Si quieres esto, utiliza el . o source comando:

    scriptdir=$(dirname "$BASH_SOURCE")    # Find the current script's directory
    . "$scriptdir/Subfolder/b.sh"          # Source a script in a subdirectory of that

    Tenga en cuenta que como el script de origen comparte variables, si redefine scriptdir como su que afectará también a su valor en el script de llamada. Tenga en cuenta que el . no tiene nada que ver con el "." de ./scriptname -- que es sólo una ruta relativa que comienza desde el directorio actual, no un comando.

AppleAyuda.com

AppleAyuda es una comunidad de usuarios de los productos de Apple en la que puedes resolver tus problemas y dudas.
Puedes consultar las preguntas de otros usuarios, hacer tus propias preguntas o resolver las de los demás.

Powered by:

X