Publi

Cómo extraer ruta, nombre de fichero y extensión en Bash de forma nativa para nuestros scripts

7959831794_e5699df68b_k
Bash tiene infinidad de opciones, y en los últimos años se ha extendido muchísimo y nos permite hacer cosas muy chulas. Aunque un sistema con tantas opciones como este, es también un poco lioso y difícil de aprender. Por eso en ocasiones viene bien una chuleta para realizar operaciones sencillas que pueden llegar a ser un poco rebuscadas como obtener el nombre de un fichero y su extensión.

Bash, al ser un intérprete de comandos de consola, una de sus principales funciones es trabajar con archivos y cuando queremos utilizar archivos, tenemos que jugar con sus posibles nombres, para ello, deberíamos poder extraer fácilmente la ruta de un archivo, su nombre y separarlo de la extensión. Por ejemplo, si queremos transformar varios archivos de un directorio de jpg a png, o hacer un script que trate de forma los archivos de imagen y de otra los vídeos, o incluso contar cuántos archivos tienen qué extensión…

Para ello, y a modo de autochuleta también, vamos a plantear varios ejemplos en los que se utilizan los modificadores # y % de expansión de parámetros en Bash:

1
2
3
4
5
6
7
#!/bin/bash
FICHERO="archivo.txt"
NOMBRE="${FICHERO%.*}"
EXTENSION="${FICHERO##*.}"

echo $NOMBRE
echo $EXTENSION

Si ejecutamos esto veremos que primero se mostrará el nombre (archivo) y luego la extensión (txt), aunque, esto deberíamos complicarlo un poco más, y plantearnos preguntas para verificar que funciona en todos los casos, por ejemplo, ¿qué pasaría si el archivo no tiene extensión? En este caso, devolvería el mismo nombre del archivo, y eso puede darnos problemas, para solucionarlo, plantearemos EXTENSION de la siguiente forma:

1
EXTENSION=$([[ "$FICHERO" = *.* ]] && echo "${FICHERO##*.}")

Ahora bien, ¿qué pasaría si nos pasan un archivo con doble extensión? Como «archivo.tar.bz2», la variable NOMBRE contendría (archivo.tar) y EXTENSION contendría (bz2). Esto puede ser útil en ciertas ocasiones, por ejemplo, podríamos recorrer todas las posibles extensiones del archivo:

1
2
3
4
5
6
7
8
9
10
11
FICHERO="archivo.tar.bz2"
NOMBRE="${FICHERO%.*}"
EXTENSION="${FICHERO##*.}"

echo $EXTENSION

while [ -n "$EXTENSION" ]; do
   FICHERO="${FICHERO%.*}";
   EXTENSION=$([[ "$FICHERO" = *.* ]] && echo "${FICHERO##*.}");
   echo $EXTENSION;
done

Pero si queremos extraer todas las extensiones juntas del archivo, deberíamos hacer:

1
EXTENSION=$([[ "$FICHERO" = *.* ]] && echo "${FICHERO#*.}")

Y si queremos el nombre sin ninguna extensión:

1
NOMBRE="${FICHERO%%.*}"

Lo que variamos es el número de % y de # que colocamos. En este caso, si utilizamos # estaremos eliminando el prefijo de un patrón, es decir, la parte a la izquierda, y como eliminamos *. queremos decir que eliminamos todo lo que hay delante del punto, ahora si usamos un sólo # estaremos eliminando lo menor posible y si usamos dos, lo mayor posible. De esta forma ${FICHERO#*.} al eliminar poco, nos devuelve todas las extensiones y ${FICHERO#*.}, al encontrar el patrón más grande posible, muestra sólo la última extensión.

De esta forma, nos podemos crear nuestras propias funciones:

1
2
3
4
5
6
7
8
9
10
11
function my_filename()
{
  local FILE="$1"
  [[ "$2" = "1" ]] && echo "${FILE%.*}" || echo "${FILE%%.*}"
}

function my_extension()
{
  local FILE="$1"
  [[ "$FILE" = *.* ]] && ( [[ "$2" = "1" ]] && echo "${FILE#*.}" || echo "${FILE##*.}")
}

Así si hacemos varias llamadas:

$ my_filename archivo
archivo
$ my_filename archivo.tar
archivo
$ my_filename archivo.tar.bz2
archivo
$ my_filename archivo.tar.bz2 1
archivo.tar

$ my_extension archivo

$ my_extension archivo.tar
tar
$ my_extension archivo.tar.bz2
bz2
$ my_extension archivo.tar.bz2 1
tar.bz2

Incluyendo directorios

Si queremos que estas funciones separen también nombres de archivo de directorios tenemos varias opciones. Una de ellas es utilizar basename y dirname, que son dos comandos que muchas veces están disponibles para extraer nombres de archivos y nombres de directorios, así:

$ basename /usr/share/sane/xsane/archivo.tar.bz2
archivo.tar.bz2
$ dirname /usr/share/sane/xsane/archivo.tar.bz2
/usr/share/sane/xsane

Aunque si queremos una solución puramente hecha en Bash, y así evitar hacer llamadas externas y ganar algo de rendimiento podemos utilizar las mismas técnicas anteriores. Es más, primero, vamos a incluir rutas de archivo con las funciones anteriores, a ver qué pasa:

$ my_filename «/usr/share/sane/xsane/archivo.tar.bz2»
/usr/share/sane/xsane/archivo
$ my_extension «/usr/share/sane/xsane/archivo.tar.bz2»
bz2

En principio el nombre incluye la ruta completa, pero la extensión se comporta bien, aunque si el directorio contiene un punto también…

$ my_extension /etc/init.d/lm-sensors
d/lm-sensors

Por tanto, primero vamos a intentar eliminar las rutas, y extraer el nombre de archivo base. Esto lo podemos hacer basándonos en el patrón entre la última barra y el final del nombre, o lo que es lo mismo, eliminando desde el principio del nombre hasta la última barra:

$ echo «${FICHERO##*/}»

y para extraer la ruta solamente, podremos utilizar algo similar a la extensión:

$ $([[ «$FICHERO» = */* ]] && echo «${FICHERO%/*}»)

Esto mismo, lo podemos trasladar a las funciones, de la siguiente forma:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
function my_filename()
{
  local FILE="$1"
  FILE="${FILE##*/}"
  [[ "$2" = "1" ]] && echo "${FILE%.*}" || echo "${FILE%%.*}"
}

function my_extension()
{
  local FILE="$1"
  FILE="${FILE##*/}"

  [[ "$FILE" = *.* ]] && ( [[ "$2" = "1" ]] && echo "${FILE#*.}" || echo "${FILE##*.}")
}

function my_dirname()
{
  local PATH="$1"

  [[ "$PATH" = */* ]] && echo "${PATH%/*}"
}

Con las que tendremos un acceso más fácil y amigable para nuestros scripts.

Foto principal: Christopher Adams

También podría interesarte....

There are 14 comments left Ir a comentario

  1. Pingback: Cómo extraer ruta, nombre de fichero y extensión en Bash de forma nativa para nuestros scripts | PlanetaLibre /

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

    These biggest web slots are a game-changer. Thanks for sharing the excitement. สล็อตเว็บใหญ่ สุด

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

    Exceptionally fascinating data, worth suggesting. Be that as it may, I suggest this: pasar 123 slot

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

    I can suggest essentially not too bad and even dependable tips, accordingly see it: 안전놀이터

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

    I’d be interested to know if the type of material used in slots affects their durability. สล็อตเว็บตรง แตกง่าย

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

    I am another client of this site so here I saw different articles and posts posted by this site,I inquisitive more enthusiasm for some of them trust you will give more data on this points in your next articles. รวมสล็อตทุกค่าย

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

    Welcome to the gathering of my life here you will master every little thing about me. 블로그

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

    Astounding, this is awesome as you need to take in more, I welcome to This is my page. เกมสล็อตโรม่า

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

    Amazing learning and I get a kick out of the opportunity to give this kind of information to my sidekicks and desire they like it they why I do ป๊อกเด้ง ออนไลน์

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

    It is incredibly average to see the best inconspicuous components presented in a basic and seeing way. best concierge doctor

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

    Astounding read, Positive webpage, where did u think of the data on this posting?I have perused a couple of the articles on your site now, and I extremely like your style. You rock and please keep up the compelling work. สล็อตเว็บตรง แตกง่าย

  12. Rank Xone /
    Usando Google Chrome Google Chrome 122.0.0.0 en Windows Windows NT

    It’s predominant, however , look at material at the road address. https://123b.video/

  13. rayed shah /
    Usando Google Chrome Google Chrome 123.0.0.0 en Windows Windows NT

    FLORAL STUDIO You possess put a crucial offspring.. Blesss intended for applying.. When i may want to review superior most current orders with this blog site.. keep placing..

  14. Giovanni /
    Usando Google Chrome Google Chrome 123.0.0.0 en Windows Windows NT

    It seems like you’re interested in a specific webpage or topic related to fire watch guard services in New York. If you have a webpage you’d like me to analyze or if you have any specific questions about fire watch guard services, feel free to share them, and I’ll do my best to provide you with insights and information.
    When it comes to VIP bodyguard services in New York City, you want to ensure the safety and security of high-profile individuals, celebrities, executives, and dignitaries. Here’s what to consider when selecting VIP bodyguard services:NYC Personal Bodyguards Services

Leave a Reply