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!" } |
Tabla de contenidos
¿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:
o
o si tengo /home/gaspy/scripts en mi variable PATH, puedo estar en /tmp o en cualquier ruta de mi ordenador y ejecutar simplemente:
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.
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
Pingback: Píldora Bash: Incluir archivos en nuestro script sin miedo a que nos cambien el directorio de ejecución | PlanetaLibre /
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
¡Muchas gracias por tus lecciones! Gracias a ti todo me va bien.
sur ron
I found this post very exciting. I am also sending it to my friends to enjoy this blog.
The Bear Season 2 Berzatto Jacket
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
I’m on a mission to conquer each of these colossal web slots. Let the games begin. สล็อตเว็บใหญ่ สุด
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
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!!!! 메이저사이트
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. 메이저사이트
I’ve been on the lookout for slots that won’t break easily. เว็บสล็อตแตกง่าย
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
It is to some degree phenomenal, but then look at the guidance at this treat. เว็บรวมสล็อตทุกค่าย
Gives you the best site address I know there alone you’ll discover how simple it is. สล็อตโรม่า
For some individuals this is the best arrangement here perceive how to do it. Pokdeng
It is to some degree phenomenal, but then look at the guidance at this treat. 대구블로그
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. 안전놀이터
This is essential, however it’s important to enable you to make a beeline for it weblink: ประโยคจีบ ภาษาจีน
For what reason do just such a great amount of composed regarding this matter? Here you see more. ความ เป็น มา ของ ภาษา จีน
I am keen on such themes so I will address page where it is cool depicted. ที่เที่ยวประเทศไทย
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 ! นักร้องลูกทุ่งหญิงรุ่นใหม่
I genuinely like you’re making style, inconceivable information, thankyou for posting. ปลาที่เลี้ยงง่ายที่สุด
I should state just that its magnificent! The blog is instructive and dependably create astonishing things. มูนไนท์ มาร์เวล
Benefit as much as possible from primarily premium substances – you will discover him or her for: เกมผีที่เล่นกับเพื่อนได้
Locate the best articles on is my companion’s profile page. สูตรน้ำผัดไทย เข้มข้น
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. หนัง เกี่ยว กับ ผจญ ภัย
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… อาหารว่างไทยง่ายๆ
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
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. 프리카지노 쿠폰
Card games, dice games – the casino has it all! 로즈카지노 쿠폰
Hallo guys, selamat datang di situs OKEPLAY777, pernahkah anda mendengar atau sudah bermain disini ?, Mari kita bahas sedikit tentang kelebihan situs slot online ini, sebagai situs slot gacor hari ini yang menggunakan slot server thailand terbaru gampang menang dengan winrate tertinggi di bandingkan situs lain, bermain di OKEPLAY777 memiliki experience yang berbeda pada saat mendapatkan kemenangan sensasional hanya dengan modal deposit slot dana Rp.15,000 dan menang berapapun di bayar tanpa potongan.
Curriculum and Instruction (Curriculum and Instruction) , this is the job of a design master! You have to think of ways to create attractive courses, and you have to think about how to teach so that students can learn better. 美国代写
ufa wallet 789 ผู้ให้บริการสปอร์ตออนไลน์ และคาสิโนเต็มรูปแบบ เล่นเพลินเกินห้ามใจ ทำกำไรได้ทุกวัน
High cost of living : In many foreign regions, especially in developed countries, the cost of living (such as housing, food, transportation, etc.) is generally high. This means that the person or company providing the service needs a higher income to cover these basic expenses. 北美代写