Publi

Píldora Bash: Incluir archivos en nuestro script sin miedo a que nos cambien el directorio de ejecución

Incluir archivos en Bash sin complicaciones

Es una buena práctica en cualquier lenguaje de programación, siempre que sea posible, el tener el código dividido en varios archivos. Esas divisiones harán que nuestro código esté mejor organizado en bloques o compartimentos diferenciados. Y, por supuesto, en nuestros shell scripts no vamos a ser menos.

De hecho, es muy común tener varios shell scripts en un directorio y todos ellos compartirán un código común. Y, por supuesto, está muy feo copiar y pegar ese código común en todos los archivos. Principalmente porque si necesitamos modificar ese código, debemos cambiarlo en todos los archivos, y eso puede llegar a ser muy pesado.

Por ello, vamos a hacer un pequeño programa, un hola mundo para la inclusión de scripts en Bash. Muy sencillo:
principal.sh:

1
2
3
4
5
#!/bin/bash

. funciones.sh

holamundo

functiones.sh:

1
2
3
4
function holamundo()
{
        echo "Hola Mundo!"
}

¿Por qué no ./funciones.sh?

Cuando utilizamos ./funciones.sh, o bash funciones.sh estaremos ejecutando el fichero y, las variables y funciones declaradas dentro de funciones.sh no podrán ser llamadas desde principal.sh. Más o menos nos interesa que el archivo principal contenga las declaraciones que hay en funciones.sh.

Muy sencillo, ahora la pega

Esto en teoría está muy bien, pero en la pŕactica se nos van a presentar algunos problemas:

No llamamos al script desde el directorio donde está creado

Sino que ponemos su ruta absoluta o relativa, o puede que lo tengamos en el $PATH. En mi caso yo tengo el script en /home/gaspy/scripts/principal.sh. Si estoy en mi $HOME puedo escribir:

scripts/principal.sh

o
/home/gaspy/scripts/principal.sh

o si tengo /home/gaspy/scripts en mi variable PATH, puedo estar en /tmp o en cualquier ruta de mi ordenador y ejecutar simplemente:
principal.sh

El problema aquí es que principal.sh siempre buscará functiones.sh en el directorio actual desde el que lo estemos ejecutando, y no siempre entrará en /home/gaspy/scripts/.

Una solución muy sencilla es escribir la ruta absoluta donde se encuentra el fichero al incluirlo (en principal.sh):

1
2
3
4
5
#!/bin/bash

. /home/gaspy/scripts/funciones.sh

holamundo

Así, en principio, no vamos a tener problema. Aunque si compartimos nuestros scripts con nuestros amigos, o los publicamos en github, estaríamos obligando a todo el mundo a tener el script en la misma ruta, y a lo mejor alguien quiere tenerlos en otro directorio, /home/pepe/scripts, /home/alice/scripts/, o /home/strawberry/local/bin.

Entonces tenemos que hacer que esta inclusión sea independiente de la ruta desde la que se llame el programa. Para ello tenemos varias formas. En principal.sh:

1
2
3
4
5
6
#!/bin/bash

SCRIPT_SOURCE="$(dirname "${BASH_SOURCE[0]}")"
. "$SCRIPT_SOURCE"/funciones.sh

holamundo

De esta manera, almacenamos en la variable SCRIPT_SOURCE el directorio donde está el script que hemos llamado, es decir, principal.sh y en función de la ruta de principal.sh incluimos funciones.sh . Por lo que, si nuestro funciones.sh está dentro de lib podríamos hacer:

1
2
SCRIPT_SOURCE="$(dirname "${BASH_SOURCE[0]}")"
. "$SCRIPT_SOURCE/lib/funciones.sh"

Son importantes las comillas dobles que vemos en el código, ya que si el directorio donde se encuentran los archivos tiene espacios (o, mejor dicho, tiene algún carácter del $IFS) podemos tener un problema al localizarlos.

Por ahora, todo parece funcionar bien. Tanto si llamamos desde ruta absoluta, relativa, incluimos el ejecutable en el $PATH o ejecutamos el archivo desde el mismo directorio. Pero, como somos muy enrevesados, vamos a dar una vuelta de tuerca más. Creando un enlace al archivo ejecutable en otro directorio y llamando a éste.

ln -s /home/gaspy/scripts/principal.sh /usr/local/bin
/usr/local/bin/principal.sh

Aunque bien podríamos haber ejecutado simplemente principal.sh porque /usr/local/bin/ suele estar en el $PATH y no tenemos por qué poner la ruta completa. El problema aquí es que el script que ejecutamos es /usr/local/bin/principal.sh y funciones.sh no está en /usr/local/bin sino en /home/gaspy/scripts/ por lo que debemos resolver la ruta del enlace para hallar el directorio real donde se encuentran los archivos. Para ello podemos hacer lo siguiente:

1
2
3
4
5
6
#!/bin/bash

SCRIPT_SOURCE="$(dirname "$(readlink -f "${BASH_SOURCE[0]}")")"
. "
$SCRIPT_SOURCE/funciones.sh"

holamundo

En realidad, tener un enlace al ejecutable no es tan raro. Puede que tengamos una serie de scripts en un directorio y sólo queramos que el ejecutable esté en el $PATH o tal vez tengamos un directorio cuyos archivos se ejecutan cuando ocurre un evento, en lugar de tener los ejecutables en dicho directorio podemos tener enlaces a los mismos y si algo cambia no tenemos que tocar los archivos, sólo los enlaces.

Hasta el momento, igual que utilizamos ${BASH_SOURCE[0]}, podríamos utilizar $0, al final es el nombre del archivo que se ha ejecutado. Aunque $BASH_SOURCE tiene una funcionalidad extra, contiene todos los archivos que se han incluido para llegar al archivo actual. Si A, incluye B y B incluye C, desde A, BASH_SOURCE sólo contendrá un archivo, desde B, contendrá 2 y desde C contendrá 3.

Archivos que no deben ser ejecutados

En nuestro caso, funciones.sh no debe ser ejecutado directamente. Podemos quitarle permisos de ejecución, pero tampoco nos frenaría demasiado. El objetivo de no poder ejecutar el script es que pueda revelar información del sistema o pueda causar un mal funcionamiento. Así que estaría bien que el script se detuviera cuando intentemos ejecutarlo. Esto lo haremos con $BASH_SOURCE, contando cuántos elementos tiene. En este caso, si el array tiene sólo un elemento estaremos ante una ejecución directa del programa. Si $BASH_SOURCE tiene más elementos, estaremos incluyendo el archivo desde otro ejecutable principal. Con esto, incluso podremos restringir quién nos incluye.

Podemos hacer por ejemplo en funciones.sh

1
2
3
4
5
6
7
8
9
10
11
12
13
#!/bin/bash

if ((${#BASH_SOURCE[@]}==1)); then
        echo "Este archivo no puede ser ejecutado" >&2
        exit
fi

function holamundo()
{
        echo "Hola Mundo!"
}

echo "Inicializo funciones..."

Por lo tanto, lo primero que verifica el archivo es que no es una ejecución directa. Así el programa funcionará si llamamos a principal.sh (incluso mostrando el mensaje «Inicializo funciones…» y nos mostrará un error si llamamos a funciones.sh. También podemos hacer exit directamente, eso ya, a nuestro gusto.

Foto principal: Olga Gorbunova

También podría interesarte....

There are 29 comments left Ir a comentario

  1. Pingback: Píldora Bash: Incluir archivos en nuestro script sin miedo a que nos cambien el directorio de ejecución | PlanetaLibre /

  2. Andrew Mark /
    Usando Google Chrome Google Chrome 117.0.0.0 en Windows Windows NT

    This is excellent article, thank you for the share! This is what I am looking for, hope in future you will continue sharing such an superb work.
    Chicago Bulls Varsity Jacket

  3. Sergio /
    Usando Google Chrome Google Chrome 116.0.0.0 en Mac OS X Mac OS X 10.15.7

    ¡Muchas gracias por tus lecciones! Gracias a ti todo me va bien.
    sur ron

  4. Mike Rooney /
    Usando Google Chrome Google Chrome 119.0.0.0 en Windows Windows NT

    I found this post very exciting. I am also sending it to my friends to enjoy this blog.
    The Bear Season 2 Berzatto Jacket

  5. Andrew Mark /
    Usando Google Chrome Google Chrome 119.0.0.0 en Windows Windows NT

    Excellent article. The writing style which you have used in this article is very good and it made the article of better quality.
    Sherlock Holmes Jacket

  6. jsimitseo /
    Usando Google Chrome Google Chrome 120.0.0.0 en Windows Windows NT

    I’m on a mission to conquer each of these colossal web slots. Let the games begin. สล็อตเว็บใหญ่ สุด

  7. WilliamSEO /
    Usando Google Chrome Google Chrome 120.0.0.0 en Windows Windows NT

    Decent data, profitable and fantastic plan, as offer well done with smart thoughts and ideas, loads of extraordinary data and motivation, both of which I require, on account of offer such a supportive data here. pasar123 gacor

  8. WilliamSEO /
    Usando Google Chrome Google Chrome 120.0.0.0 en Windows Windows NT

    I require you to thank for your period of this radiant read!!! I definately value every last bit of it and I have you bookmarked to take a gander at new stuff of your blog an outright need read blog!!!! 메이저사이트

  9. WilliamSEO /
    Usando Google Chrome Google Chrome 120.0.0.0 en Windows Windows NT

    You bear through a wonderful opening. I rational soundness unquestionably quarry it besides by and by propose to my buddys. I am reserved they assurance be profited from this scene. 메이저사이트

  10. jsimitseo /
    Usando Google Chrome Google Chrome 120.0.0.0 en Windows Windows NT

    I’ve been on the lookout for slots that won’t break easily. เว็บสล็อตแตกง่าย

  11. WilliamSEO /
    Usando Google Chrome Google Chrome 120.0.0.0 en Windows Windows NT

    I went onto your blog while centering just marginally submits. Decent procedure for next, I will be bookmarking without a moment’s delay grab your entire ascents… B2C booking platform

  12. jsimitseo /
    Usando Google Chrome Google Chrome 120.0.0.0 en Windows Windows NT

    It is to some degree phenomenal, but then look at the guidance at this treat. เว็บรวมสล็อตทุกค่าย

  13. jsimitseo /
    Usando Google Chrome Google Chrome 120.0.0.0 en Windows Windows NT

    Gives you the best site address I know there alone you’ll discover how simple it is. สล็อตโรม่า

  14. jsimitseo /
    Usando Google Chrome Google Chrome 120.0.0.0 en Windows Windows NT

    For some individuals this is the best arrangement here perceive how to do it. Pokdeng

  15. jsimitseo /
    Usando Google Chrome Google Chrome 120.0.0.0 en Windows Windows NT

    It is to some degree phenomenal, but then look at the guidance at this treat. 대구블로그

  16. WilliamSEO /
    Usando Google Chrome Google Chrome 120.0.0.0 en Windows Windows NT

    Decent data, profitable and fantastic plan, as offer well done with smart thoughts and ideas, loads of extraordinary data and motivation, both of which I require, on account of offer such a supportive data here. 안전놀이터

  17. william SEO /
    Usando Mozilla Firefox Mozilla Firefox 122.0 en Windows Windows NT

    This is essential, however it’s important to enable you to make a beeline for it weblink: ประโยคจีบ ภาษาจีน

  18. william SEO /
    Usando Mozilla Firefox Mozilla Firefox 122.0 en Windows Windows NT

    For what reason do just such a great amount of composed regarding this matter? Here you see more. ความ เป็น มา ของ ภาษา จีน

  19. william SEO /
    Usando Mozilla Firefox Mozilla Firefox 122.0 en Windows Windows NT

    I am keen on such themes so I will address page where it is cool depicted. ที่เที่ยวประเทศไทย

  20. william SEO /
    Usando Mozilla Firefox Mozilla Firefox 122.0 en Windows Windows NT

    I am continually hunting on the web down articles that can help me. There is clearly a great deal to think about this. I think you made some great focuses in Features too. Continue working, extraordinary job ! นักร้องลูกทุ่งหญิงรุ่นใหม่

  21. william SEO /
    Usando Mozilla Firefox Mozilla Firefox 122.0 en Windows Windows NT

    I genuinely like you’re making style, inconceivable information, thankyou for posting. ปลาที่เลี้ยงง่ายที่สุด

  22. william SEO /
    Usando Mozilla Firefox Mozilla Firefox 122.0 en Windows Windows NT

    I should state just that its magnificent! The blog is instructive and dependably create astonishing things. มูนไนท์ มาร์เวล

  23. william SEO /
    Usando Mozilla Firefox Mozilla Firefox 122.0 en Windows Windows NT

    Benefit as much as possible from primarily premium substances – you will discover him or her for: เกมผีที่เล่นกับเพื่อนได้

  24. william SEO /
    Usando Mozilla Firefox Mozilla Firefox 122.0 en Windows Windows NT

    Locate the best articles on is my companion’s profile page. สูตรน้ำผัดไทย เข้มข้น

  25. william SEO /
    Usando Mozilla Firefox Mozilla Firefox 122.0 en Windows Windows NT

    I’m eager to reveal this page. I have to thank you for ones time for this especially fabulous read !! I unquestionably extremely loved all aspects of it and I likewise have you spared to fav to take a gander at new data in your site. หนัง เกี่ยว กับ ผจญ ภัย

  26. william SEO /
    Usando Mozilla Firefox Mozilla Firefox 122.0 en Windows Windows NT

    An obligation of appreciation is all together to share the data, continue doing magnificent… I really savored the experience of exploring your site. incredible resource… อาหารว่างไทยง่ายๆ

  27. jsimitseo /
    Usando Google Chrome Google Chrome 121.0.0.0 en Windows Windows NT

    Incredible data! I as of late went over your blog and have been perusing along. I figured I would leave my first remark. I don’t recognize what to state with the exception of that I have. concierge doctor

  28. Rank Xone /
    Usando Google Chrome Google Chrome 121.0.0.0 en Windows Windows NT

    The online casino experience is not just about luck; strategy and skill play a significant role. It adds a level of challenge that I find really engaging. 프리카지노 쿠폰

  29. Rank Xone /
    Usando Google Chrome Google Chrome 123.0.0.0 en Windows Windows NT

    Card games, dice games – the casino has it all! 로즈카지노 쿠폰

Leave a Reply to Anónimo Cancle Reply