lunes, 29 de junio de 2015

Expansión de nombres de archivos ocultos

Como sabemos, los nombres de archivo que empiezan por un punto están ocultos. La expansión de nombres de archivo también respeta este comportamiento. Una expansión como:

echo *

no revela los archivos ocultos.

Podría parecer a primera vista que podríamos incluir archivos ocultos en una expansión comenzando el patrón con un punto, así:

echo .*

Casi funciona. De todas formas, si examinamos los resultados atentamente, veremos que los nombres “.” y “..” también aparecen en los resultados. Como estos nombres se refieren al directorio actual y su directorio padre, usar este patrón probablemente producirá un resultado incorrecto. Podemos verlo si probamos el comando:

ls -d .* | less

Para ejecutar mejor una expansión de nombres de archivo en esta situación, tenemos que emplear un patrón más específico:

echo .[!.]*

Este patrón se expande en todos los nombres de archivo que empiecen con un punto, no incluye un segundo punto, seguido de cualquier otro carácter. Esto funcionará correctamente con la mayoría de archivos ocultos (aunque no incluirá archivos con varios puntos al comienzo de su nombre). El comando ls con la opción -A (“almost all” o “casi todo”) proporcionará un listado correcto de los archivos ocultos:

ls -A

viernes, 26 de junio de 2015

Expansión de nombres de archivo

El mecanismo según el cual trabajan los comodines se llama expansión de nombres de archivo. Si probamos algunas de las técnicas que hemos empleado en nuestros capítulos anteriores, veremos que son realmente expansiones. Tomemos un directorio home que aparezca de la siguiente forma:

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

podríamos llevar a cabo las siguientes expansiones:

[me@linuxbox ~]$ echo D*
Desktop Documents

y:

[me@linuxbox ~]$ echo *s
Documents Pictures Templates Videos

o también:

[me@linuxbox ~]$ echo [[:upper:]]*
Desktop Documents Music Pictures Public Templates Videos

y mirando más allá de nuestro directorio home:

[me@linuxbox ~]$ echo /usr/*/share
/usr/kerberos/share /usr/local/share

miércoles, 24 de junio de 2015

Expansión

Cada vez que escribes un comando y presionas la tecla enter, bash realiza varios procesos sobre el texto antes de llevar a cabo el comando. Hemos visto un par de casos de cómo una simple secuencia de caracteres, por ejemplo “*”, puede tener mucho significado para el shell. El proceso que hace que esto ocurra se llama expansión. Con la expansión, introduces algo y se expande en otra cosa antes de que el shell actúe sobre ello. Para demostrar qué queremos decir con esto, echemos un vistazo al comando echo. echo es un shell builtin que realiza una tarea muy simple. Muestra sus argumentos de texto en la salida estándar:

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

Es muy sencillo. Cualquier argumento que pasemos a echo se muestra. Probemos otro ejemplo:

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

Pero, ¿qué ha pasado? ¿por qué echo no ha escrito “*”? Como recordarás de nuestro trabajo con comodines, el carácter “*” significa coincidencia con cualquier carácter en el nombre de archivo, pero lo que no hemos visto en nuestra conversación original es cómo hace eso el shell. La respuesta sencilla es que el shell expande el “*” en algo más (en este ejemplo, los nombres de los archivos que se encuentran en el directorio de trabajo actual) antes de que el comando echo se ejecute. Cuando presionamos la tecla enter, el shell automáticamente expande todos los caracteres en la línea de comandos antes de que el comando sea ejecutado, por lo que el comando echo no ve el “*”, sólo su resultado expandido. Sabiendo esto, podemos ver que echo se ha comportado como se esperaba.

lunes, 22 de junio de 2015

Viendo el mundo como lo ve el shell

En este capítulo vamos a ver algo de la “magia” que ocurre en la línea de comandos cuando presionas la tecla enter. Aunque examinaremos varias características interesantes y complejas del shell, lo haremos con un único comando nuevo:
  • echo – Muestra una línea de texto

viernes, 19 de junio de 2015

Linux tiene que ver con la imaginación

Cuando me piden que explique la diferencia entre Windows y Linux, a menudo uso una analogía con un juguete.

Windows es como una Game Boy. Vas a la tienda y compras una toda brillante y nueva en su caja. La llevas a casa, la enciendes y juegas con ella. Bonitos gráficos, hermosos sonidos. Cuando pasa un rato, te cansas del juego que viene con ella y vuelves a la tienda a comprar otro. Este ciclo se repite una y otra vez. Finalmente, vuelves a la tienda y le dices a la persona que está tras el mostrador, “¡Quiero un juego que haga esto!” sólo para que te digan que ese tipo de juego no existe porque no hay “demanda” en el mercado. Entonces dices, “¡Pero sólo necesito cambiar una cosa!" La persona tras el mostrador te dice que no puedes cambiarlo. Los juegos se venden en sus cartuchos. Descubres que tu juguete está limitado a los juegos que otros han decidido que necesitas y nada más.

Linux, al contrario, es como el mecano más grande del mundo. Lo abres y sólo es una gran colección de partes. Un montón de puntales de acero, tornillos, tuercas, engranajes, poleas, motores y algunas sugerencias sobre qué puedes construir. Así que empiezas a jugar con él. Construyes una de las sugerencias y luego otra. Después de un rato descubres que tienes tus propias ideas de qué construir. Nunca más tienes que volver a la tienda, ya que tienes todo lo que necesitas. El mecano se adapta a tu imaginación. Hace lo que tú quieres.

Tu elección de juguetes es, por supuesto, algo personal,  así que ¿qué juguete encontrarías más satisfactorio?

miércoles, 17 de junio de 2015

Resumiendo

Como siempre, revisa la documentación de cada comando que hemos tratado en este capítulo. Sólo hemos visto su uso más básico. Todos tienen numerosas opciones interesantes. Según vayamos ganando experiencia con Linux, veremos que la función de redirección de la línea de comandos es extremadamente útil para solucionar problemas especializados. Hay muchos comandos que hacen uso de la entrada y salida estándar, y casi todos los programas de la línea de comandos usan el error estándar para mostrar sus mensajes informativos.

lunes, 15 de junio de 2015

Tee – Lee de stdin y lo pasa a stdout y a archivos

Siguiendo con nuestra metáfora de fontanería, Linux proporciona un comando llamado tee que crea una unión con forma de “T” en nuestra tubería. El programa tee lee la entrada estándar y la copia a la salida estándar (permitiendo que los datos continúen bajando por la tubería) y a uno o más archivos. Esto es útil para capturar el contenido de una tubería en una fase intermedia del procesamiento. Repetiremos uno de nuestros anteriores ejemplos, esta vez incluyendo tee para capturar el listado completo del directorio al archivo ls.txt antes de que grep filtre el contenido de la tubería:

[me@linuxbox ~]$ ls /usr/bin | tee ls.txt | grep zip
bunzip2
bzip2
gunzip
gzip
unzip
zip
zipcloak
zipgrep
zipinfo
zipnote
zipsplit

viernes, 12 de junio de 2015

head / tail – Muestra la primera/última parte de los archivos

Algunas veces no quieres toda la salida de un comando. Podrías querer sólo las primeras o las últimas líneas. El comando head muestra las primeras diez líneas de un archivo y el comando tail muestras las diez últimas. Por defecto, ambos comandos muestran diez líneas de texto, pero esto puede ajustarse con la opción “-n”:

[me@linuxbox ~]$ head -n 5 ls-output.txt
total 343496
-rwxr-xr-x 1 root root  31316 2007-12-05 08:58 [
-rwxr-xr-x 1 root root   8240 2007-12-09 13:39 411toppm
-rwxr-xr-x 1 root root 111276 2007-11-26 14:27 a2p
-rwxr-xr-x 1 root root  25368 2006-10-06 20:16 a52dec
[me@linuxbox ~]$ tail -n 5 ls-output.txt
-rwxr-xr-x 1 root root   5234 2007-06-27 10:56 znew
-rwxr-xr-x 1 root root    691 2005-09-10 04:21 zonetab2pot.py
-rw-r--r-- 1 root root    930 2007-11-01 12:23 zonetab2pot.pyc
-rw-r--r-- 1 root root    930 2007-11-01 12:23 zonetab2pot.pyo
lrwxrwxrwx 1 root root      6 2008-01-31 05:22 zsoelim -> soelim

También se pueden usar en tuberías:

[me@linuxbox ~]$ ls /usr/bin | tail -n 5
znew
zonetab2pot.py
zonetab2pot.pyc
zonetab2pot.pyo
zsoelim

tail tiene una opción que nos permite ver los archivos en tiempo real. Esto es útil para ver el progreso de los archivos de logs tal como se van escribiendo. En el siguiente ejemplo, veremos el archivo messages en /var/log (o el archivo /var/log/syslog si messages no existe). Se requieren privilegios de superusuario para hacerlo en algunas distribuciones Linux, ya que el archivo /var/log/messages podría contener información de seguridad:

[me@linuxbox ~]$ tail -f /var/log/messages
Feb 8 13:40:05 twin4 dhclient: DHCPACK from 192.168.1.1
Feb 8 13:40:05 twin4 dhclient: bound to 192.168.1.4 -- renewal in 1652 seconds.
Feb 8 13:55:32 twin4 mountd[3953]: /var/NFSv4/musicbox exported to both 192.168.1.0/24 and twin7.localdomain in 192.168.1.0/24,twin7.localdomain
Feb 8 14:07:37 twin4 dhclient: DHCPREQUEST on eth0 to 192.168.1.1 port 67
Feb 8 14:07:37 twin4 dhclient: DHCPACK from 192.168.1.1
Feb 8 14:07:37 twin4 dhclient: bound to 192.168.1.4 -- renewal in 1771 seconds.
Feb 8 14:09:56 twin4 smartd[3468]: Device: /dev/hda, SMART Prefailure Attribute: 8 Seek_Time_Performance changed from 237 to 236
Feb 8 14:10:37 twin4 mountd[3953]: /var/NFSv4/musicbox exported to both 192.168.1.0/24 and twin7.localdomain in 192.168.1.0/24,twin7.localdomain
Feb 8 14:25:07 twin4 sshd(pam_unix)[29234]: session opened for user me by (uid=0)
Feb 8 14:25:36 twin4 su(pam_unix)[29279]: session opened for user root by me(uid=500)

Usando la opción “-f”, tail continua monitorizando el archivo y cuando se le añaden nuevas líneas, inmediatamente aparecen en la pantalla. Esto continúa hasta que pulses Ctrl-c.

miércoles, 10 de junio de 2015

grep – Imprime líneas que coinciden con un patrón

grep es un programa poderoso utilizado para encontrar patrones de texto en los archivos. Se usa así:

grep patrón [archivo...]

Cuando grep encuentra un “patrón” en el archivo, muestra las líneas que lo contienen. El patrón que grep puede encontrar puede ser muy complejo, pero por ahora nos concentraremos en simples coincidencias de texto. Trataremos patrones avanzados, llamados expresiones regulares en un capítulo posterior.

Digamos que queremos encontrar todos los archivos, en nuestra lista de programas, que tengan la palabra “zip” incluida en el nombre. Una búsqueda así debería darnos una idea de algunos de los programas en nuestro sistema que tienen algo que ver con la compresión de archivos. Haríamos esto:

[me@linuxbox ~]$ ls /bin /usr/bin | sort | uniq | grep zip
bunzip2
bzip2
gunzip
gzip
unzip
zip
zipcloak
zipgrep
zipinfo
zipnote
zipsplit

Hay un par de opciones útiles para grep: “-i” que hace que grep no diferencie entre mayúsculas y minúsculas cuando haga la búsqueda (normalmente las búsquedas distinguen entre mayúsculas y minúsculas) y “-v” que le dice a grep que sólo muestre las lineas que no coincidan con el patrón.

lunes, 8 de junio de 2015

wc – Muestra el número de líneas, palabras y bytes

El comando wc (word count – contador de palabras) se usa para mostrar el número de líneas, palabras y bytes contenidos en un archivo. Por ejemplo:

[me@linuxbox ~]$ wc ls-output.txt
7902 64566 503634 ls-output.txt

En este caso muestra tres números: líneas, palabras y bytes contenidos en ls-output.txt. Como nuestros anteriores comandos, si lo ejecutamos sin argumentos, wc acepta la entrada estándar. La opción “-l” limita su salida para mostrar sólo el número de líneas. Añadirlo a una tubería es una forma útil de contar cosas. Para ver el número de elementos que tenemos en nuestra lista ordenada, podemos hacer esto:

[me@linuxbox ~]$ ls /bin /usr/bin | sort | uniq | wc -l
2728

viernes, 5 de junio de 2015

uniq – Muestra u omite líneas repetidas

El comando uniq a menudo se usa junto con sort. uniq acepta una lista ordenada de datos de la entrada estándar o de un argumento que sea un nombre de archivo (mira la man page de uniq para saber más detalles) y, por defecto, elimina los duplicados de la lista. Así, que para estar seguro de que nuestra lista no tiene duplicados (ya sabes, algunos programas con el mismo nombre pueden aparecer tanto en el directorio /bin como en /usr/bin) añadiremos uniq a nuestra tubería:

[me@linuxbox ~]$ ls /bin /usr/bin | sort | uniq | less

En este ejemplo, usamos uniq para eliminar duplicados de la salida del comando sort. Si, en lugar de eso, queremos ver la lista de duplicados, añadiremos la opción “-d” a uniq así:

[me@linuxbox ~]$ ls /bin /usr/bin | sort | uniq -d | less

jueves, 4 de junio de 2015

Filtros

Las tuberías a menudo se usan para realizar complejas operaciones con datos. Es posible poner varios comandos juntos en una tubería. Con frecuencia, a los comandos usados de esta forma se les llama filtros. Los filtros toman entradas, las cambian de alguna manera y las mandan a la salida. El primero que probaremos es sort. Imagina que queremos hacer una lista combinada de todos los programas ejecutables en /bin y en /usr/bin, que los ponga en orden y los veamos:

[me@linuxbox ~]$ ls /bin /usr/bin | sort | less

Como hemos especificado dos directorios  (/bin y /usr/bin), la salida de ls debería haber consistido en dos listas ordenadas, una para cada directorio. Pero incluyendo sort, en nuestra tubería, hemos cambiado los datos para producir una única lista ordenada.

miércoles, 3 de junio de 2015

La diferencia entre > y |

A primera vista, podría ser difícil de comprender la redirección realizada por el operador tubería (pipeline)  | frente a la del operador de redirección >. Simplificando, el operador de redirección conecta un comando con un archivo mientras que el operador tubería conecta la salida de un comando con la entrada de un segundo comando.

comando1 > archivo1
comando1 | comando2

Mucha gente intentará lo siguiente cuando estén aprendiendo las tuberías, “sólo para ver lo que sucede.”

comando1 > comando2

Respuesta: A veces algo realmente malo.

Aquí tenemos un ejemplo real enviado por un lector que estaba administrando un servidor basado en Linux. Como superusuario, hizo esto:

# cd /usr/bin
# ls > less

El primer comando le colocó en el directorio donde están almacenados la mayoría de los programas y el segundo comando le dijo al shell que sobrescriba el archivo less con la salida del comando ls. Como el directorio /usr/bin ya contenía un archivo llamado “less” (el programa less), el segundo comando sobrescribió el archivo del programa less con el texto de ls y en consecuencia destruyó el programa less en su sistema.

La lección aquí es que el operador de redirección crea o sobrescribe archivos silenciosamente, así que necesitas tratarlo con mucho respeto.

martes, 2 de junio de 2015

Tuberías (Pipelines)

La capacidad de los comandos de leer datos de la entrada estándar y mandarlos a la salida estándar la utiliza una característica del shell llamada tubería (pipeline). Usando el operador tubería “|” (la barra vertical), la salida estándar de un comando puede ser entubada o canalizada hacia la entrada estándar de otro:

comando1 | comando2

Para demostrarlo plenamente, vamos a necesitar algunos comandos. ¿Recuerdas que dijimos que había uno que ya conocíamos que acepta entrada estándar? Es less. Podemos usar less para mostrar, página a página, la salida de cualquier comando que mande sus resultados a la salida estándar:

[me@linuxbox ~]$ ls -l /usr/bin | less

¡Esto es extremadamente útil! Usando esta técnica, podemos examinar convenientemente la salida de cualquier comando que produzca salida estándar.

lunes, 1 de junio de 2015

cat – Concatenando archivos

El comando cat lee uno o más archivos y los copia a la salida estándar de la siguiente forma:

cat [archivo...]

En la mayoría de los casos, puedes pensar que cat es análogo al comando TYPE de DOS. Puedes usarlo para mostrar archivos sin paginar, por ejemplo:

[me@linuxbox ~]$ cat ls-output.txt

mostrará el contenido del archivo ls-output.txt. cat a menudo se usa para mostrar archivos de texto cortos. Como cat puede aceptar más de un archivo como argumento, también se puede usar para unir archivos. Imagina que hemos descargado un gran archivo que ha sido dividido en múltiples partes (los archivos multimedia a menudo están divididos de esta forma en Usenet), y queremos unirlos de nuevo. Si los archivos se llamaran:

movie.mpeg.001 movie.mpeg.002 ... movie.mpeg.099

podríamos unirlos de nuevo con este comando:

cat movie.mpeg.0* > movie.mpeg

Como los comodines siempre expanden sus resultados en orden, los argumentos se distribuirán en el orden correcto.

Todo esto está muy bien, pero ¿qué tiene esto que ver con la entrada estándar? Nada todavía, pero probemos algo más. Qué pasa si usamos “cat” sin argumentos:

[me@linuxbox ~]$ cat

No ocurre nada, sólo se queda quieto como si se hubiera quedado colgado. Podría parecer eso, pero realmente está haciendo lo que se supone que debe hacer.

Si no le damos argumentos a cat, lee de la entrada estándar y como la entrada estándar está, por defecto, asignada al teclado, ¡está esperando a que tecleemos algo! Prueba a añadir el siguiente texto y pulsa Enter:

[me@linuxbox ~]$ cat
The quick brown fox jumped over the lazy dog.

Ahora, pulsa Ctrl-d (es decir, mantén pulsada la tecla Ctrl y luego pulsa “d”) para decirle a cat que ha alcanzado el final del archivo (EOF – end of file) en la entrada estándar:

[me@linuxbox ~]$ cat
The quick brown fox jumped over the lazy dog.
The quick brown fox jumped over the lazy dog.

En ausencia de nombres de archivo como argumentos, cat copia la entrada estándar a la salida estándar, así que vemos nuestra línea de texto repetida. Podemos usar este comportamiento para crear archivos de texto cortos. Digamos que queremos crear un archivo llamado “lazy_dog.txt” conteniendo el texto de nuestro ejemplo. Podríamos hacer esto:

[me@linuxbox ~]$ cat > lazy_dog.txt
The quick brown fox jumped over the lazy dog.

Escribe el comando seguido del texto que queremos colocar en el archivo. Recuerda pulsar Ctrl-d al final. Usando la línea de comandos, ¡hemos implementado el procesador de texto más tonto del mundo! Para ver nuestros resultados, podemos usar cat para copiar de nuevo el archivo a stdout:

[me@linuxbox ~]$ cat lazy_dog.txt
The quick brown fox jumped over the lazy dog.

Ahora que sabemos cómo cat acepta la entrada estándar, además de nombres de archivo como argumentos, probemos redirigiendo la entrada estándar:

[me@linuxbox ~]$ cat < lazy_dog.txt
The quick brown fox jumped over the lazy dog.

Usando el operador de redirección “<”, hemos cambiado el origen de la entrada estándar del teclado al archivo lazy_dog.txt. Vemos que el resultado es el mismo que pasarle un nombre de archivo como argumento. Esto no es particularmente útil en comparación con pasar un nombre de archivo como argumento, pero sirve para demostrar el uso de un archivo como fuente de la entrada estándar. Otros comandos hacen un mejor uso de la entrada estándar, como veremos pronto.

Antes de seguir, echa un vistazo a la man page de cat, ya que tiene varias opciones interesantes.