viernes, 31 de julio de 2015

Edición de la línea de comandos

bash usa una biblioteca (una colección compartida de rutinas que pueden utilizar diferentes programas) llamada Readline para implementar la edición de la línea de comandos. Ya hemos visto algo de esto. Sabemos, por ejemplo, que las teclas de las flechas mueven el cursor, pero hay muchas más características. Piensa en ello como herramientas adicionales que podemos emplear en nuestro trabajo. No es importante aprenderlo todo sobre ellas, pero muchas son muy útiles. Cógelas y elígelas como quieras.

Nota: Algunas de las siguientes secuencias de teclas (particularmente aquellas que usan la tecla Alt) podrían ser interceptadas por el GUI para otras funciones. Todas las secuencias de teclas deberían funcionar adecuadamente cuando usamos una consola virtual.

miércoles, 29 de julio de 2015

Trucos avanzados del teclado

A menudo bromeo y describo Unix como “el sistema operativo para la gente que le gusta escribir”. Desde luego, el hecho de que incluso tenga una línea de comandos es una prueba de ello. Pero a los usuarios de la línea de comandos no les gusta tanto escribir. ¿Por qué, si no, tantos comandos tienen nombres cortos como cp, ls, mv y rm? De hecho, uno de los objetivos más preciados de la línea de comandos es la pereza; hacer la mayor cantidad de trabajo con el menor número de pulsaciones. Otro objetivo es no tener que despegar nunca los dedos del teclado, no tener que coger nunca el ratón. En este capítulo, veremos las características de bash que hacen que usemos el teclado más rápido y más eficientemente.

Los siguientes comandos harán su aparición:
  • clear – Borra la pantalla
  • history – Muestra los contenidos de la lista del historial

lunes, 27 de julio de 2015

Para saber más

  • La man page de bash tiene grandes secciones tanto de expansión como de entrecomillado que cubren estos asuntos de una manera más formal.
  • El Manual de Referencia de Bash también contiene capítulos de expansión y entrecomillado:
    http://www.gnu.org/software/bash/manual/bashref.html

viernes, 24 de julio de 2015

Resumiendo

A medida que avancemos en el uso del shell, encontraremos que las expansiones y entrecomillados se usarán con mayor frecuencia, por lo que tiene sentido comprender perfectamente la forma en que funcionan. De hecho, se podría decir que son los aspectos más importantes a aprender sobre el shell. Sin una comprensión adecuada de la expansión, el shell siempre será una fuente de misterio y confusión, y perderemos mucho de su potencial.

miércoles, 22 de julio de 2015

Secuencias de escape con la barra invertida

Además de su rol como carácter de escape, la barra invertida también se usa como parte de una notación para representar ciertos caracteres especiales llamados control codes (códigos de control). Los primeros 32 caracteres en el esquema del código ASCII se usan para transmitir comandos a dispositivos de la familia de los teletipos. Algunos de estos códigos son familiares (tabulador, salto de línea y retorno de carro), mientras que otros no lo son (nulo, fin de la transmisión, y confirmación).

Secuencia de escape Significado
\a
Tono (“Alerta” - hace que el ordenador pite)
\b
Retroceder un espacio
\n
Nueva línea. En sistemas tipo Unix, produce un salto de línea.
\r
Retorno de carro.
\t
Tabulación

La tabla anterior lista algunos de las secuencias de caracteres de escape más comunes. La idea detrás de esta representación usando la barra invertida se originó en el lenguaje de programación C y ha sido adoptada por otros muchos, incluido el shell.

Añadiendo la opción “-e” a echo activaremos la interpretación de las secuencias de escape. También puedes colocarlos dentro de $' '. De esta forma, usando el comando sleep, un programa simple que sólo espera a que le digamos un número específico de segundos y luego se cierra, podemos crear un primitivo cronómetro de cuenta atrás:

sleep 10; echo -e "Time's up\a"

También podríamos hacer esto:

sleep 10; echo "Time's up" $'\a'

lunes, 20 de julio de 2015

Caracteres de escape

Algunas veces sólo queremos entrecomillar un único carácter. Para hacerlo, podemos preceder un carácter con una barra invertida, que en este contexto se llama carácter de escape. A menudo se hace dentro de las comillas dobles para prevenir selectivamente una expansión:

[me@linuxbox ~]$ echo "The balance for user $USER is: \$5.00"
The balance for user me is: $5.00

También es común usar caracteres de escape para eliminar el significado especial de un carácter en un nombre de archivo. Por ejemplo, es posible usar caracteres en nombres de archivo que normalmente tienen un significado especial para el shell. Esto incluye “$”, “!”, “&”, “ “, y otros. Para incluir un carácter especial en un nombre de archivo  puedes hacer esto:

[me@linuxbox ~]$ mv bad\&filename good_filename

Para permitir que la barra invertida aparezca, la “escapamos” escribiendo “\\”. Fíjate que dentro de las comillas simples, la barra invertida pierde su significado especial y se trata como un carácter ordinario.

viernes, 17 de julio de 2015

Comillas simples

Si necesitamos suprimir todas las expansiones, usamos comillas simples. A continuación vemos una comparación entre sin comillas, comillas dobles y comillas simples:

[me@linuxbox ~]$ echo text ~/*.txt {a,b} $(echo foo) $((2+2)) $USER
text /home/me/ls-output.txt a b foo 4 me
[me@linuxbox ~]$ echo "text ~/*.txt {a,b} $(echo foo) $((2+2)) $USER"
text ~/*.txt {a,b} foo 4 me
[me@linuxbox ~]$ echo 'text ~/*.txt {a,b} $(echo foo) $((2+2)) $USER'
text ~/*.txt {a,b} $(echo foo) $((2+2)) $USER

Como podemos ver, con cada nivel sucesivo de entrecomillado, se van suprimiendo más expansiones.

miércoles, 15 de julio de 2015

Comillas dobles

El primer tipo de entrecomillado que vamos a ver son las comillas dobles. Si colocas un texto dentro de comillas dobles, todos los caracteres especiales utilizados por el shell perderán su significado especial y serán tratados como caracteres ordinarios. Las excepciones son “$”, “\” (barra invertida), y “`” (tilde invertida). Esto significa que la  separación de palabras, expansión de nombres de archivo, expansión de la tilde de la ñ y la expansión con llaves están suprimidas, pero la expansión con parámetros, la expansión aritmética y la sustitución de comandos sí que funcionarán. Usando comillas dobles, podemos manejar nombres de archivo que contengan espacios en blanco. Digamos que somos la desafortunada víctima de un archivo llamado two words.txt. Si tratáramos de usarlo en la línea de comandos, la separación de palabras haría que fuera tratado como dos argumentos separados en lugar del único argumento que queremos:

[me@linuxbox ~]$ ls -l two words.txt
ls: cannot access two: No such file or directory
ls: cannot access words.txt: No such file or directory

Usando comillas dobles, paramos la separación de palabras y obtenemos el resultado deseado; más aún, incluso podemos reparar el daño causado:

[me@linuxbox ~]$ ls -l "two words.txt"
-rw-rw-r-- 1 me me 18 2008-02-20 13:03 two words.txt
[me@linuxbox ~]$ mv "two words.txt" two_words.txt

¡Ahí lo tienes! Ahora no tenemos que seguir escribiendo esas malditas comillas dobles.

Recuerda, la expansión con parámetros, la expansión aritmética y la sustitución de comandos siguen funcionando dentro de las comillas dobles:

[me@linuxbox ~]$ echo "$USER $((2+2)) $(cal)"
me 4 February 2008
Su Mo Tu We Th Fr Sa
                1  2
 3  4  5  6  7  8  9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29

Deberíamos tomarnos un momento para mirar el efecto de las comillas dobles en la sustitución de comandos. Primero miremos un poco más atentamente a cómo funciona la separación de palabras. En nuestro ejemplo anterior, vimos como la separación de palabras parece eliminar los espacios sobrantes en nuestro texto:

[me@linuxbox ~]$ echo this is a      test
this is a test

Por defecto, la separación de palabras busca la presencia de espacios, tabulaciones y líneas nuevas (caracteres de salto de línea) y las trata como delimitadores entre palabras. Esto significa que los espacios, tabuladores y nuevas líneas, cuando no están entre comillas dobles, no se consideran parte del texto. Sólo sirven como separadores. Como separan las palabras en diferentes argumentos, nuestro ejemplo de la línea de comandos contiene un comando seguido de cuatro argumentos distintos. Si añadimos comillas dobles:

[me@linuxbox ~]$ echo "this is a       test"
this is a      test

la separación de palabras se suprime y los espacios en blanco no se tratan como separadores, en lugar de eso pasan a ser parte del argumento. Una vez que añadimos las comillas dobles, nuestra línea de comandos contiene un comando seguido de un único argumento.

El hecho de que las líneas nuevas sean consideradas como separadores por el mecanismo de separación de palabras provoca un interesante, aunque sutil, efecto en la sustitución de comandos. Considera lo siguiente:

[me@linuxbox ~]$ echo $(cal)
February 2008 Su Mo Tu We Th Fr Sa 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
[me@linuxbox ~]$ echo "$(cal)"
    February 2008
Su Mo Tu We Th Fr Sa
                 1 2
       3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29

En el primer caso,  la sustitución de comandos sin comillas resulta en una línea de comandos que contiene 38 argumentos. En el segundo, una linea de comandos con un argumento que incluye los espacios en blanco y las nuevas líneas.

lunes, 13 de julio de 2015

Entrecomillado

Ahora que hemos visto de cuantas formas el shell puede realizar expansiones, es hora de aprender cómo podemos controlarlas. Tomemos un ejemplo:

[me@linuxbox ~]$ echo this is a      test
this is a test

o:

[me@linuxbox ~]$ echo The total is $100.00
The total is 00.00

En el primer ejemplo, la separación de palabras del shell ha eliminado el espacio en blanco adicional de la lista de argumentos del comando echo. En el segundo ejemplo, la expansión con parámetros sustituyó con una cadena vacía el valor de “$1” porque era una variable indefinida. El shell proporciona un mecanismo llamado quoting (entrecomillado) para suprimir selectivamente expansiones no deseadas.

viernes, 10 de julio de 2015

Sustitución de comandos

La sustitución de comandos nos permite usar la salida de un comando como una expansión:

[me@linuxbox ~]$ echo $(ls)
Desktop Documents ls-output.txt Music Pictures Public Templates Videos

Una de mis favoritas hace algo como esto:

[me@linuxbox ~]$ ls -l $(which cp)
-rwxr-xr-x 1 root root 71516 2007-12-05 08:58 /bin/cp

Aquí hemos pasado el resultado de which cp como un argumento para el comando ls, de esta forma obtenemos el listado del programa cp sin tener que saber su ruta completa. No estamos limitados sólo a comandos simples. Se pueden usar tuberías enteras (sólo se muestra una salida parcial):

[me@linuxbox ~]$ file $(ls -d /usr/bin/* | grep zip)

/usr/bin/bunzip2:       symbolic link to `bzip2'

/usr/bin/bzip2:         ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.9, stripped

/usr/bin/bzip2recover:  ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.9, stripped

/usr/bin/funzip:        ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.9, stripped

/usr/bin/gpg-zip:       Bourne shell script text executable

/usr/bin/gunzip:        symbolic link to `../../bin/gunzip'

/usr/bin/gzip:          symbolic link to `../../bin/gzip'

/usr/bin/mzip:          symbolic link to `mtools'

En este ejemplo, el resultado de la tubería se convierte en la lista de argumentos del comando file.

Hay una sintaxis alternativa para la sustitución de comandos en programas de shell antiguos que también es soportada por bash. Utiliza tildes invertidas en lugar del signo del dólar y los paréntesis:

[me@linuxbox ~]$ ls -l `which cp`
-rwxr-xr-x 1 root root 71516 2007-12-05 08:58 /bin/cp

miércoles, 8 de julio de 2015

Expansión con parámetros

En este capítulo, sólo vamos a tratar brevemente la expansión con parámetros, pero lo trataremos más extensamente más tarde. Es una función que es más útil en scripts de shell que directamente en la línea de comandos. Muchas de sus capacidades tienen que ver con la capacidad del sistema de almacenar pequeños trozos de datos y dar a cada trozo un nombre. Muchos de esos trozos, más apropiadamente llamados variables, están disponibles para su examen. Por ejemplo, la variable llamada “USER” contiene tu nombre de usuario. Para invocar la expansión con parámetros y revelar el contenido de USER deberías hacer esto:

[me@linuxbox ~]$ echo $USER
me

Para ver una lista de las variables disponibles, prueba esto:

[me@linuxbox ~]$ printenv | less

Habrás notado que con otros tipos de expansión, si escribes mal un patrón, la expansión no se lleva a cabo y el comando echo simplemente mostrará el patrón que has escrito mal. Con la expansión con parámetros, si escribes mal el nombre de la variable, la expansión se realizará, pero dando como resultado una cadena vacía:

[me@linuxbox ~]$ echo $SUER
[me@linuxbox ~]$

lunes, 6 de julio de 2015

Expansión con llaves

Quizás la expansión más extraña es la llamada expansión con llaves. Con ella, puedes crear múltiples cadenas de texto a partir de un patrón que contenga llaves. Aquí tienes un ejemplo:

[me@linuxbox ~]$ echo Front-{A,B,C}-Back
Front-A-Back Front-B-Back Front-C-Back

Los patrones a expandir con llaves pueden contener un prefijo llamado preamble (preámbulo) y un sufijo llamado postcript (postdata). La expresión entre llaves puede contener una lista de cadenas separadas por comas o un rango de números enteros o caracteres individuales. El patrón no debe contener espacios en blanco. Aquí hay un ejemplo usando un rango de números enteros:

[me@linuxbox ~]$ echo Number_{1..5}
Number_1 Number_2 Number_3 Number_4 Number_5

Los números enteros también pueden tener ceros a la izquierda así:

[me@linuxbox ~]$ echo {01..15}
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15
[me@linuxbox ~]$ echo {001..15}
001 002 003 004 005 006 007 008 009 010 011 012 013 014 015

Un rango de letras en orden inverso:

[me@linuxbox ~]$ echo {Z..A}
Z Y X W V U T S R Q P O N M L K J I H G F E D C B A

Las expansiones con llaves pueden ser anidadas:

[me@linuxbox ~]$ echo a{A{1,2},B{3,4}}b
aA1b aA2b aB3b aB4b

¿Y para qué sirve esto? La aplicación más común es hacer listas de archivos o directorios a crear. Por ejemplo, si fuésemos fotógrafos con una gran colección de imágenes que queremos organizar en años y meses, la primera cosa que deberíamos hacer es crear una serie de directorios nombrados en formato numérico “Año-Mes”. De esta forma, los directorios se ordenarán cronológicamente. Podríamos escribir la lista completa de directorios, pero sería un montón de trabajo y sería muy fácil equivocarnos. En lugar de eso, podríamos hacer esto:

[me@linuxbox ~]$ mkdir Photos
[me@linuxbox ~]$ cd Photos
[me@linuxbox Photos]$ mkdir {2007..2009}-{01..12}
[me@linuxbox Photos]$ ls
2007-01 2007-07 2008-01 2008-07 2009-01 2009-07
2007-02 2007-08 2008-02 2008-08 2009-02 2009-08
2007-03 2007-09 2008-03 2008-09 2009-03 2009-09
2007-04 2007-10 2008-04 2008-10 2009-04 2009-10
2007-05 2007-11 2008-05 2008-11 2009-05 2009-11
2007-06 2007-12 2008-06 2008-12 2009-06 2009-12

¡Muy astuto!

viernes, 3 de julio de 2015

Expansión aritmética

El shell permite realizar aritmética mediante la expansión. Esto nos permite usar el prompt del shell como una calculadora:

[me@linuxbox ~]$ echo $((2 + 2))
4

La expansión aritmética usa la forma:

$((expresión))

donde expresión es una expresión aritmética consistente en valores y operadores aritméticos.

La expansión aritmética sólo soporta enteros (números enteros sin decimales), pero puede realizar un buen número de operaciones diferentes. Aquí hay unos pocos de los operadores soportados:

Tabla 7-1: Operadores aritméticos
Operador Descripción
+ Suma
- Resta
* Multiplicación
/ División (pero recuerda, como la expansión sólo soporta enteros, los resultados serán enteros.)
% Módulo, que simplemente significa, “resto”
** Potencia

Los espacios no son significativos en las expresiones aritméticas y las expresiones pueden ser anidadas. Por ejemplo, para multiplicar 5 al cuadrado por 3:

[me@linuxbox ~]$ echo $(($((5**2)) * 3))
75

Los paréntesis sencillos pueden ser usados para agrupar subexpresiones. Con esta técnica, podemos reescribir el ejemplo anterior y obtener el mismo resultado usando una única expansión en lugar de dos:

[me@linuxbox ~]$ echo $(((5**2) * 3))
75

Aquí tenemos un ejemplo usando los operadores división y resto. Fíjate el efecto de la división con enteros:

[me@linuxbox ~]$ echo Five divided by two equals $((5/2))
Five divided by two equals 2
[me@linuxbox ~]$ echo with $((5%2)) left over.
with 1 left over.

La expansión aritmética será tratada con más detalle en el Capítulo 34.

miércoles, 1 de julio de 2015

Expansión de la tilde de la ñ

Como recordarás de nuestra introducción al comando cd, el carácter virgulilla, o tilde de la ñ (“~”) tiene un significado especial. Cuando se usa al principio de una palabra, se expande en el nombre del directorio home del usuario nombrado, o si no se nombra a ningún usuario, en el directorio home del usuario actual:

[me@linuxbox ~]$ echo ~
/home/me

Si el usuario “foo” tiene una cuenta, entonces:

[me@linuxbox ~]$ echo ~foo
/home/foo