Aprenda Linux, 101: Corrientes, tuberías y redirecciones

Siéntase cómodo con la tuberías de Linux

Si cree que las corrientes y las tuberías hacen que un experto® de Linux parezca un plomero, aquí está su oportunidad de aprender acerca de ella y de cómo redirigirlas y dividirlas. Usted incluso podrá aprender a convertir una corriente en argumentos de comandos. Usted podrá utilizar el material de este artículo para estudiar para el examen de 101®de LPI para la certificación del sistema administrador de Linux, o simplemente para aprenderlo por diversión.

Ian Shields, Senior Programmer, EMC

author photo - Ian ShieldsIan Shields trabaja en múltiples proyectos Linux para la zona Linux de developerWorks. Es Senior Programmer de IBM en el Research Triangle Park (RTP), Carolina del Norte. Ingresó a IBM en Canberra, Australia, como Systems Engineer en 1973, y desde entonces se dedica a sistemas de comunicaciones y computación ubicua en Montreal, Canadá, y en el RTP de Carolina del Norte. Es propietario de numerosas patentes y publicó diversos trabajos. Tiene una diplomatura en Matemática Pura y Filosofía de la Universidad Nacional de Australia. Es Máster y Doctor en Ciencias de la Computación de la Universidad Estatal de Carolina del Norte. Para contactar a Ian, escríbale a: ishields@us.ibm.com.


Nivel de autor contribuyente en developerWorks

08-07-2010

Acerca de esta serie

Esta serie de artículos lo ayudan a aprender las tareas de administración del sistema Linux Usted también puede utilizar el material de estos artículos para prepararse para los examenes del nivel 1 (LPIC-1) de Linux Professional Institute Certification.

Vea nuestro plan de trabajo de la serie para obtener una descripción de y un vínculo a cada artículo en esta serie. El plan de trabajo está en curso y refleja los últimos objetivos de (Abril de 2009) para los exámenes de LPIC-1: a medida que completamos los artículos, los agregaremos al plan de trabajo. En el ínterin, sin embargo, usted puede encontrar las versiones anteriores de un material similar, que dan soporte a los objetivos previos de LPIC-1, anteriores al mes de Abril de 2009, en nuestros tutoriales para la certificación de la preparación de los exámenes LPI.

Prerrequisitos

Para aprovechar al máximo los artículos de estas series, usted debe tener un conocimiento básico del sistema Linux de trabajo en el que usted pueda practicar los comandos que aparecen en este artículo. A veces las diferentes versiones de un programa le dará formato a la salida de un modo diferente, por lo tanto los resultados pueden no verse siempre exactamente como los que aparecen en los listados y en la ilustración que se muestra aquí.

Visión General

Este artículo lo pone en contacto con las técnicas básicas de Linux para redireccionar la corriente estándar de IO. Aprenda a:

  • Redireccionar la corriente estándar de IO: la entrada estándar, la salida estándar, y el error estándar
  • Direccionar la salida desde un comando hasta la entrada del otro
  • Enviar una salida tanto al stdout como a un archivo
  • Utilizar la salida del comando como los argumentos para el otro comando

Este artículo lo ayuda a prepararse para el Objetivo 103.4 en el tópico 03 del examen 101 de Linux Professional Institute's Junior Level Administration (LPIC-1). 101. El objetivo tiene un peso de 4.


Configuración de los ejemplos

En este artículo, practicaremos los comandos utilizando algunos de los archivos creados en este artículo "Learn Linux 101: Text streams and filters." Pero si usted no ha leído ese artículo, o usted no salvó los archivos con los que trabajó no ¡se haga problema! Comencemos por crear un subdirectorio en en su directorio raíz llamado lpi103-4 y creemos los archivo necesarios en él. Para hacerlo debemos abrir una ventana de texto en su directorio raíz como su directorio actual. Luego copie los contenidos del Listado 1 en la ventana para que se ejecuten los comandos que crearán el subdirectorio lpi103-4 y los archivos que usted utilizará.

Listado 1. La creación de los archivos de ejemplo archivos
mkdir -p lpi103-4 && cd lpi103-4 && {
echo -e "1 apple\n2 pear\n3 banana" > text1
echo -e "9\tplum\n3\tbanana\n10\tapple" > text2
echo "This is a sentence. " !#:* !#:1->text3
split -l 2 text1
split -b 17 text2 y; }

Su ventana debe parecerse a la del listado 2, y su actual directorio debería ser ahora el directorio lpi103-4 creado recientemente.

Listado 2. Creación del ejemplo de archivos - salida

Haga clic para ver la lista de códigos

Listado 2. Creación del ejemplo de archivos - salida

[ian@echidna ~]$ mkdir -p lpi103-4 && cd lpi103-4 && {
> echo -e "1 apple\n2 pear\n3 banana" > text1
> echo -e "9\tplum\n3\tbanana\n10\tapple" > text2
> echo "This is a sentence. " !#:* !#:1->text3echo "This is a sentence. " "This is a sentence. " "This is a sentence. ">text3
> split -l 2 text1
> split -b 17 text2 y; }
[ian@echidna lpi103-4]$

Redireccionar el IO estándar

Un shell de Linux, tal como un Bash, recibe la entrada y envía la salida como secuencias o series de caracteres. Cada carácter es independiente al anterior y del siguiente . Los caracteres no están organizados en registros estructurados o bloques de tamaño fijo. Se accede a las secuencias utilizando las técnicas del archivo IO (ya sea que la serie real de los caracteres venga desde o se dirija hacia un archivo), un teclado, una ventana en una pantalla, o algún otro dispositivo de IO. Los shells de Linux utilizan tres series estándar de I/O, cada una de ellas está asociada a un descriptor de archivos muy conocido:

  1. stdout es la serie de salida estándar, que muestra la salida de los comandos. Cuenta con un descriptor de archivos 1
  2. stderr es la serie de error estándar, que muestra la salida de los errores desde los comandos. Cuenta con un descriptor de archivos 2.
  3. stdin es la serie de entrada estándar, que proporcina la entrada a los comandos. Cuenta con un descriptor de archivos 0.

Las series de entrada permiten la entrada a los programas, generalmente desde las pulsaciones en el teclado de la terminal. Las series de salida imprimen los caracteres del texto, por lo general para la terminal. La terminal era en un principio una máquina de escribir ASCII o una pantalla de terminal, pero ahora es con mayor frecuencia una ventana de texto o un desktop gráfico.

Si usted ya ha estudiado el artículo "Learn Linux 101: Text streams and filters," una parte del material que se halla en este artículo le será muy familiar.

Redirecionar la salida

Existen dos modos de redireccionar la salida a un archivo:

n>
redireccione la salida desde el descriptor del archivon a un archivo. Usted deberá tener autoridad para escribir al archivo. Si el archivo no existe, éste es creado. Si ya existe, los contenidos existentes generalmente se pierden sin previo aviso.
n>>
también redirecciona la salida desde el descriptor del archivo n a un archivo. Nuevamente, deberá tener la autorización para escribir en el archivo. Si el archivo no existe, éste es creado. Si existe, la salida se anexa al archivo existente.

La n en n> o en n>> se refiere al descriptor del archivo. Si se omite, se asume la salida estándar. El listado 3 ilustra el uso de la redirección para separar la salida estándar y el error estándar desde el comando ls utilizando los archivos creados anteriormente en nuestro directorio lpi103-4. También ilustramos las salidas anexas a los archivos existentes.

Listado 3. Redirección de la salida
[ian@echidna lpi103-4]$ ls x* z*
ls: cannot access z*: No such file or directory
xaa  xab
[ian@echidna lpi103-4]$ ls x* z* >stdout.txt 2>stderr.txt
[ian@echidna lpi103-4]$ ls w* y*
ls: cannot access w*: No such file or directory
yaa  yab
[ian@echidna lpi103-4]$ ls w* y* >>stdout.txt 2>>stderr.txt
[ian@echidna lpi103-4]$ cat stdout.txt
xaa
xab
yaa
yab
[ian@echidna lpi103-4]$ cat stderr.txt
ls: cannot access z*: No such file or directory
ls: cannot access w*: No such file or directory

Dijimos que la redirección de la salida utilizando n> generalmente sobrescribe los archivos existentes. Usted puede controlar esto con la opción noclobber del set builtin. Si ya se ha definido, usted puede anularla utilizando n> como se indica en el Listado 4.

Listado 4. Redirección de la salida con noclobber
[ian@echidna lpi103-4]$ set -o noclobber
[ian@echidna lpi103-4]$ ls x* z* >stdout.txt 2>stderr.txt
-bash: stdout.txt: cannot overwrite existing file
[ian@echidna lpi103-4]$ ls x* z* >|stdout.txt 2>|stderr.txt
[ian@echidna lpi103-4]$ cat stdout.txt
xaa
xab
[ian@echidna lpi103-4]$ cat stderr.txt
ls: cannot access z*: No such file or directory
[ian@echidna lpi103-4]$ set +o noclobber #restore original noclobber setting

A veces usted puede querer redireccionar la salida estándar y el error estándar en un archivo. Esto se suele hacer en los procesos automatizados o en "background jobs" de tal modo que usted pueda revisar la salida más tarde. Utilice &> o &>> para redireccionar la salida estándar y el error estándar al mismo lugar. Otra manera de hacerlo es redireccionar el descriptor del archivo n y luego redireccionar el descriptor del archivom hacia el mismo lugar utilizando la herramienta m>&n o m>>&n. El orden en el que se direccionan las salidas es importante. Por ejemplo,
command 2>&1 >output.txt
no es lo mismo que
command >output.txt 2>&1
En el primer caso, stderr es redireccionada a un sitio actual de stdout y luego stdout es redireccionada a la salida .txt, pero esta segunda redirección afectó sólo a stdout, no a stderr. En el segundo caso, stderr es redireccionada al sitio actual de stdout y ésa es la salida.txt. Nosotros ilustramos estas redirecciones en el Listado 5. Observe en el último comando que la salida estándar fue redireccionada después de que el error estándar, por lo tanto la salida del error estándar todavía va a la ventana de la terminal.

Listado 5. Redireccionar dos series a un archivo
[ian@echidna lpi103-4]$ ls x* z* &>output.txt
[ian@echidna lpi103-4]$ cat output.txt
ls: cannot access z*: No such file or directory
xaa
xab
[ian@echidna lpi103-4]$ ls x* z* >output.txt 2>&1
[ian@echidna lpi103-4]$ cat output.txt
ls: cannot access z*: No such file or directory
xaa
xab
[ian@echidna lpi103-4]$ ls x* z* 2>&1 >output.txt # stderr no va a la salida.txt
ls: cannot access z*: No such file or directory
[ian@echidna lpi103-4]$ cat output.txt
xaa
xab

En otras ocasiones es posible que usted deseara ignorar por completo la salida estándar o el error estándar. Para hacer esto, hay que redirigir la serie adecuada al archivo vacío, /dev/null. El Listado 6 indica cómo ignorar la salida del error desde el comando ls, y también utiliza el comando cat para mostrarle que/dev/null está, realmente, vacío.

Listado 6. Ignorar la salida utilizando/dev/null
[ian@echidna lpi103-4]$ ls x* z* 2>/dev/null
xaa  xab
[ian@echidna lpi103-4]$ cat /dev/null

Redireccionar la entrada

Del mismo modo que podemos redireccionar las series stdout y stderr, también podemos redireccionar stdin desde un archivo, utilizando el operador <. Si usted ya estudió el artículo "Learn Linux 101: Text streams and filters," recordará, en nuestro debate acerca de sort y uniq que utilizamos el comando tr para reemplazar los espacios en nuestro archivo text1 con tabs. En ese ejemplo utilizamos la salida desde el comando cat para crear la entrada estándar para el comando tr. En lugar de llamarlo innecesariamente cat, podemos utilizar la redirección de la entrada para convertir los espacios a tabs, como se muestra en el Listado 7.

Listado 7. Redireccionar la entrada
[ian@echidna lpi103-4]$ tr ' ' '\t'<text1
1       apple
2       pear
3       banana

Shells, incluyendo bash, tienen también el concepto de un here-document, que es otra forma de redireccionar la entrada. Se utiliza << junto con una palabra, tal como END, para un marcador o centinela a fin de indicar el final de la entrada. Lo mostramos en el Listado 8.

Listado 8. Redirección de la entrada con un here-document
[ian@echidna lpi103-4]$ sort -k2 <<END
> 1 apple
> 2 pear
> 3 banana
> END
1 apple
3 banana
2 pear

Usted se preguntará qué hubiera sucedido si no hubiera podido escribir sort -k2, ingresar sus datos, y luego pulsar Ctrl-d para indicar el final del ingreso. La respuesta breve es que usted hubiera podido, pero no hubiera aprendido sobre here-documents. La verdadera respuesta es que here-documents es utilizado con mayor frecuencia en los scripts de shell. (Un script no posee ningún otro modo de indicar qué líneas del script deben ser tratadas como una entrada). Dado que los scripts de shell realizan un amplio uso de la tabulación para dar una sangría a los fines de la legibilidad, hay otro giro para here-documents. Si usted utiliza <<- en lugar de sólo <<, los tabs principales son eliminados.

En el >LIstado 9 creamos un carácter de tabulación cautivo utilizando la sustitución del comando y luego creando un script muy pequeño de shell que contenga dos comandos cat, de tal modo que cada uno pueda leer desde un here-document. Observe que utilizamos END como el centinela del here-document que estamos leyendo desde la terminal. Si utilizamos la misma palabra para el centinela dentro del script, podremos finalizar nuestra escritura en forma prematura. Por lo tanto, utilizamos EOF en su lugar. Después de crearse nuestro script, utilizamos el . comando (dot) para originarlolo que significa ejecutarlo en el contexto actual de shell.

Lisado 9. Redireccionamiento con here-document
[ian@echidna lpi103-4]$ ht=$(echo -en "\t")
[ian@echidna lpi103-4]$ cat<<END>ex-here.sh
> cat <<-EOF
> apple
> EOF
> ${ht}cat <<-EOF
> ${ht}pear
> ${ht}EOF
> END
[ian@echidna lpi103-4]$ cat ex-here.sh
cat <<-EOF
apple
EOF
        cat <<-EOF
        pear
        EOF
[ian@echidna lpi103-4]$ . ex-here.sh
apple
pear

Usted aprenderá más de la sustitución de los comandos y sobre el script en los siguientes artículos de esta serie. Vea nuestro series roadmap for a description of and link to each article in the series.


Crear tuberías

En el artículo "Learn Linux 101: Text streams and filters," describimos el filtrado de texto como el proceso de tomar una secuencia de texto de entrada y realizar una conversión en la misma antes de enviarlo a una secuencia de salida. Dicho filtrado se realiza con frecuencia construyendo unatubería de comandos en donde la salida de un comando es direccionada o redirigida para ser usada como entrada para la siguiente. El uso de tuberías de esta manera no se limita a las secuencias de texto, aunque a menudo es donde se las utilizan.

Direccionar stdout a stdin

Usted utiliza el operador | (pipe) entre dos comandos para dirigir el stdout del primero al stdin del segundo. Podrá construir un conducto más largo agregando más comandos y más operadores de conductos. Cualquiera de los comandos puede tener opciones o argumentos. Muchos utilizan un guión (-) en lugar de un nombre de archivo como argumento para indicar cuándo una entrada debería provenir de un stdin en lugar de hacerlo de un archivo. Verifique en las páginas del manual para estar seguro del comando. La construcción de los conductos largos de comandos de tal modo que cada uno tenga una capacidad limitada es una forma muy común que tiene Linux y UNIX®para la realización de las tareas. En el conducto hipotético en el Listado 10, command2 y command3 ambos tienen un parámetro, mientras que command3 utiliza el - parámetro únicamente para indicar la entrada desde stdin.

Listado 10. Salida del conducto a través de varios comandos
command1 | command2 paramater1 | command3 parameter1 - parameter2 | command4

Algo para tener en cuenta es que los conductos solamente conducen desde stdout hasta stdin. Usted no puede usar 2| para canalizar stderr aisladamente, al menos, no con las herramientas que hemos aprendido hasta ahora. Si stderr hubiera sido redireccionada a stdout, ambas secuencias serían canalizadas. En el Listado 11 ilustramos un comando ls poco probable con cuatro argumentos comodines que no se encuentran en orden alfabético, luego usamos una clase de tubería, la normal combinada y la salida de errores.

Listado 11. Direccionar dos secuencias de salida
[ian@echidna lpi103-4]$ ls y* x* z* u* q*
ls: cannot access z*:No such file or directory
ls: cannot access u*: No such file or directory
ls: cannot access q*: No such file or directory
xaa  xab  yaa  yab
[ian@echidna lpi103-4]$ ls y* x* z* u* q*  2>&1 |sort
ls: cannot access q*: No such file or directory
ls: cannot access u*: No such file or directory
ls: cannot access z*: No such file or directory
xaa
xab
yaa
yab

Una ventaja de los sistemas de los conductos de Linux y UNIX es que, a diferencia de algunos otros sistemas operativos populares, no existe un archivo intermedio involucrado con un conducto. El stdout del primer comando no se escribe en un archivo y luego es leído por el segundo comando. En el artículo "Learn Linux, 101: File and directory management," usted aprende cómo archivar y comprimir un archivo en un paso utilizando el comando tar. Si por casualidad está trabajando en un sistema UNIX en donde el comando tar no da soporte a la compresión utilizando -z (para gzip) o -j (para bzip2), eso no es un problema. Usted puede utilizar una tubería como

bunzip2 -c somefile.tar.bz2 | tar -xvf -

para realizar la tarea.

El comienzo de las tuberías con un archivo en lugar de un stdout

En las tuberías anteriores comenzamos con algunos comandos que generaron la salida y luego se direccionó esa salida a cada etapa de la tubería. ¿Qué sucedería si quisiéramos comenzar con un archivo de datos que ya existe? Muchos de los comandos tomarían un stdin o un archivo como entrada, por lo tanto esos no serían un problema. Si usted tuviese un filtro que requiriera una entrada desde stidin, debería pensar en usar el comando cat para copiar el archivo a stdout, lo que funcionaría. Sin embargo, puede usar la redirección de la entrada para el primer comando y direccionar la salida del comando a través del resto de la tubería para la solución más habitual. Sólo utilice el operador < para redirigir el stdin de su primer comando al archivo que desee procesar.


Usar la salida como argumento

En el debate anterior sobre las tuberías, usted aprendió cómo tomar la salida de un comando y utilizarla como la entrada a otro comando. Supongamos en cambio, que quiera utilizar la salida de un comando o los contenidos de un archivo como argumento a un comando en lugar de como entrada. Las tuberías no funcionarían en ese caso. Existen tres métodos comunes:

  1. El comando xargs
  2. El comando find con la opción -exec
  3. Comando sustitución

Usted aprenderá sobre las dos primeras ahora. Ya vio el ejemplo del comando de sustitución en el Listado 9 cuando creamos un carácter de tabulación cautivo. La sustitución del comando se utiliza en la línea de comando, pero con más frecuencia en el scripting; usted conocerá más acerca de este tema y sobre el scripting en los artículos posteriores de esta serie. Vea nuestro series roadmap para obtener una descripción de cada artículo en la serie y un vínculo a él.

Usar elcomando xargs

El comando cxargs lee la entrada estándar y luego crea y ejecuta los comandos con la entrada como parámetros. Si no hay ningún comando dado, entonces el comando echo es utilizado. El Listado 12 es un ejemplo básico que utiliza nuestro archivo text1, el que contiene tres líneas, cado una con dos palabras..

Listado 12. Usar xargs
[ian@echidna lpi103-4]$ cat text1
1 apple
2 pear
3 banana
[ian@echidna lpi103-4]$ xargs<text1
1 apple 2 pear 3 banana

¿Por qué sólo hay una línea de salida desde xargs? Por omisión, xargs interrumpe la entrada en los espacios en blanco, y cada token resultante se convierte en un parámetro. Sin embargo, cuando xargs crea el comando pasarán tantos parámetros a la vez como se posible. Usted puede anular este procedimiento con -n, o con el parámetro --max-args. En el listado 13 ilustramos el uso de ambas formas y agregamos una invocación explícita de echo a nuestro uso de xargs.

Listado 13. Usar xargs y echo
[ian@echidna lpi103-4]$ xargs<text1 echo "args >"
args > 1 apple 2 pear 3 banana
[ian@echidna lpi103-4]$ xargs --max-args 3 <text1 echo "args >"
args > 1 apple 2
args > pear 3 banana
[ian@echidna lpi103-4]$ xargs -n 1 <text1 echo "args >"
args > 1
args > apple
args > 2
args > pear
args > 3
args > banana

Si la entrada contiene espacios que están protegidos por comillas simples o dobles, o por la barra invertida de escape, entonces xargs no interrumpirá el ingreso a dichos puntos. El Listado 14 ilustra este punto.

Listado 14. Usar xargs con encomillado
[ian@echidna lpi103-4]$ echo '"4 plum"' | cat text1 -
1 apple
2 pear
3 banana
"4 plum"
[ian@echidna lpi103-4]$ echo '"4 plum"' | cat text1 - | xargs -n 1
1
apple
2
pear
3
banana
4 plum

Hasta el momento, todos los argumentos han sido agregados al final del comando. Si usted tiene la obligación de utilizarlos como argumentos con otros argumentos a continuación, entonces utilice la opción -I para especificar una cadena de reemplazo. En cualquier lugar del comando en que se produzca la cadena de reemplazo que usted pida ejecutarxargsserá reemplazada por un argumento. Cuando usted haga esto, solamente un argumento será pasado a cada comando. Sin embargo, el argumento será creado desde una línea de ingreso completa, no sólo desde un único token. Usted también puede utilizar la opción -L de xargs al tener que tratar a las líneas como argumentos en lugar de hacerlo por la omisión de los tokens individuales delimitados por los espacios en blanco. El uso de la opción-I implica -L 1. El listado 15 muestra los ejemplos del uso de ambos-I y -L

Listado 15. Usar xargs con líneas de entrda
[ian@echidna lpi103-4]$ xargs -I XYZ echo "START XYZ REPEAT XYZ END" <text1
START 1 apple REPEAT 1 apple END
START 2 pear REPEAT 2 pear END
START 3 banana REPEAT 3 banana END
[ian@echidna lpi103-4]$ xargs -IX echo "<X><X>" <text2
<9      plum><9 plum>
<3      banana><3       banana>
<10     apple><10       apple>
[ian@echidna lpi103-4]$ cat text1 text2 | xargs -L2
1 apple 2 pear
3 banana 9 plum
3 banana 10 apple

Aunque nuestros ejemplos hayan usado archivos de textos simples como ilustración, usted rara vez deseará utilizar xargs con una entrada como ésta. Por lo general estará tratando con una larga lista de archivos generados de un comando como ls, find, o grep. El Listado 16 muestra una forma en la que se podría pasar un listado de directorios a través de xargs a un comando como grep.

Listado 16. Usar xargs con las listas de archivos
[ian@echidna lpi103-4]$ ls |xargs grep "1"
text1:1 apple
text2:10        apple
xaa:1 apple
yaa:1

¿Qué sucede en el último ejemplo si uno o más de los nombres del archivo contienen un espacio? Si usted sólo utiliza el comando como en el Listado 16, podría encontrar un error. En el mundo real, su lista de archivos pude venir de alguna fuente como un script o un comando personalizado, en lugar de venir de ls, o usted podría desear pasarlo a través de otro estadio del conducto para luego filtrarlo, entonces lo que vamos a ignorar es el hecho de que usted podría solamente utilizar grep "1" * en lugar de esta construcción.

Para el comando ls, usted puede utilizar la opción --quoting-style para obligar al nombre del archivo con problemas a ser citado entre comillas o a ser evitado. Una mejor solución, cuando está disponible, es la opción -0 de xargs, de tal modo que el carácter nulo (\0) sea utilizado para delimitar los argumentos de entrada. Aunque ls no posee una opción que suministre los nombres de los archivos terminados en cero como salida, muchos comandos la poseen.

En el Listado 17 primero copiamos el text1 al "text 1" y luego mostramos algunas maneras de utilizar una lista de nombres de los archivos que contengan espacios en blanco con xargs. Estos son para ilustrar los conceptos, ya que xargs podría ser dificil de dominar. En particular, el último ejemplo para convertir los caracteres de la línea nueva a nulos no funcionaría si alguno de los nombres de los archivos ya contuvieran los caracteres de la línea nueva. En la próxima parte del artículo, veremos una solución más consistente utilizando el comando find para generar una salida más adecuada delimitada por la nulidad.

Listado 17. Uso de xargs con espacios en blanco en los nombres de los archivos
[ian@echidna lpi103-4]$ cp text1 "text 1"
[ian@echidna lpi103-4]$ ls *1 |xargs grep "1" # error
text1:1 apple
grep: text: No such file or directory
grep: 1: No such file or directory
[ian@echidna lpi103-4]$ ls --quoting-style escape *1
text1  text\ 1
[ian@echidna lpi103-4]$ ls --quoting-style shell *1
text1  'text 1'
[ian@echidna lpi103-4]$ ls --quoting-style shell *1 |xargs grep "1"
text1:1 apple
text 1:1 apple
[ian@echidna lpi103-4]$ # Illustrate -0 option of xargs
[ian@echidna lpi103-4]$ ls *1 | tr '\n' '\0' |xargs -0 grep "1"
text1:1 apple
text 1:1 apple

El comando xargs no construirá comandos largos en forma arbitraria. Hasta Linux kernel 2.26.3, el tamaño máximo de un comando estaba limitado. Un comando comorm somepath/*, para un directorio que contenga muchos archivos con nombres largos podría fallar con un mensaje que indique que la lista de argumentos era demasiado extensa. En los anteriores sistemas Linux, o en los sistemas UNIX que aún pueden tener dicha limitación, es útil saber cómo utilizar xargs para que usted pueda manejar dichas situaciones

Usted puede utilizar la opción --show-limits para mostrar los límites por omisión de xargs, y la opción -s para limitar el tamaño de los comandos de salida a un número máximo específico de caracteres. Ver las páginas del manual para obtener otras opciones que no hemos tratado aquí.

Usar el comando find con la opción-exec o con xargs

En este artículo "Learn Linux, 101: File and directory management," usted aprende cómo utilizar el comandofind para encontrar los archivos por nombre, por la hora de modificación, por el tamaño o por otras características. Una vez que usted encuentra esa serie de archivos, con frecuencia deseará hacer algo con ella: eliminarla, copiarla en otro sitio, cambiarle el nombre o alguna otra operación. Ahora veremos la opción -exec de find, que posee una funcionalidad similar a la de find y canaliza la salida a xargs.

Listado 18. Usar find y -exec
[ian@echidna lpi103-4]$ find text[12] -exec cat text3 {} \;
This is a sentence.  This is a sentence.  This is a sentence.
1 apple
2 pear
3 banana
This is a sentence.  This is a sentence.  This is a sentence.
9       plum
3       banana
10      apple

En comparación con lo que usted ya ha aprendido acerca del uso de xargs, existen algunas deferencias.

  1. Usted debe incluir el {} para marcar dónde va el nombre del archivo en el comando. No se agregará en forma automática al final.
  2. Debe terminar el comando con un punto y coma y éste debe ser escapado; \;, ';', o ";" lo hará.
  3. El comando se ejecutará una vez para cada archivo de entrada.

Intente ejecutar find text[12] |xargs cat text3 para que usted mismo pueda ver las diferencias.

Ahora retornemos al espacio en blanco en el nombre del archivo. En el listado 19 intentamos usar find con -exec en lugar de ls con xargs.

Listado 19. Usar find y -exec con los espacios en blanco en los nombres de los archivos
[ian@echidna lpi103-4]$ find . -name "*1" -exec grep "1" {} \;
1 apple
1 apple

Hasta ahora está todo bien. ¿Pero no hay algo que falta? ¿Qué archivos contienen las líneas encontradas por grep? El nombre del archivo falta porque find llamó a grep una vez para cada archivo, y grep es lo suficientemente inteligente como para saber que si usted sólo le entrega el nombre de un archivo, entonces no necesita decirle de qué archivo se trata.

Podríamos ver xargs en su lugar, pero ya hemos visto los problemas con los espacios en blanco en los nombres de los archivos. También aludimos al hecho de que find pudiera producir una lista de nombres de archivos con delimitadores nulos, y eso es lo que la opción -print0 hace. Las versiones modernas de find pueden ser delimitadas con un signo + en lugar de un punto y coma, y esto hace que find pase tantos nombres como le sea posible en una invocación de un comando, del mismo modo que funciona xargs. No es necesario decir que usted puede usar solamante {} una vez en este caso, y éste deberá ser el último parámetro del comando. El Listado 20 nos muestra ambos métodos.

Listado 20. Usar find and xargs con los espacios en blanco en los nombres de los archivos
[ian@echidna lpi103-4]$ find . -name "*1" -print0 |xargs -0 grep "1"
./text 1:1 apple
./text1:1 apple
[ian@echidna lpi103-4]$ find . -name "*1" -exec grep "1" {} +
./text 1:1 apple
./text1:1 apple

Generalmente, cualquier método funcionaría, y la elección es a menudo una cuestión de estilo personal. Recuerde que direccionar cosas con espacios en blanco desprotegidos o espacios vacíos puede causar problemas, por lo tanto utilice la opción -print0 con find si está direccionando la salida a xargs, y utlice la opción -0 para indicarle axargs que espere la entrada delimitada nula. Otros comandos, incluyendo tar, también dan soporte a la entrada delimitada nula utilizando la opción -0 de tal modo que usted debería utilizarla para los comandos que le dan soporte, a menos que esté seguro de que su lista de ingreso no será un problema.

Un último comentario al operar sobre las listas de archivos. Es siempre una buena idea probar a fondo su lista y también probar su comando con mucho cuidado antes de comprometerse a realizar una operación masiva, tal como quitar o renombrar los archivos. Tener un buen backup puede resultar muy útil también.


División de la salida

Esta sección termina con un breve debate sobre un comando más. A veces usted puede querer ver la salida en su pantalla mientras está salvando simultáneamente una copia para verla más tarde. Aunque pudiera hacer esto redireccionando la salida del comando a un archivo en una ventana y luego utilizando tail -fn1 para seguir la salida en otra pantalla, el uso del comando tee es más sencillo.

Usted utiliza tee con una tubería. Los argumentos son un archivo (o múltiples archivos) para una salida estándar. La opción -a anexa en lugar de sobrescribir los archivos. Como vimos antes en nuestro debate acerca de las tuberías necesita redirigir stderr a stdout antes de direccionarla a tee si desea salvar ambas. El Listado 21 muestra tee utilizado para salvar la salida en dos archivos, f1 y f2.

Listado 21. División de stdout con tee
[ian@echidna lpi103-4]$ ls text[1-3]|tee f1 f2
text1
text2
text3
[ian@echidna lpi103-4]$ cat f1
text1
text2
text3
[ian@echidna lpi103-4]$ cat f2
text1
text2
text3

Recursos

Aprender

Obtener los productos y tecnologías

  • Con IBM trial software, disponible para su descarga directamente desde developerWorks, construya su próximo proyecto de desarrollo en Linux.

Comentar

Comentarios

developerWorks: Ingrese

Los campos obligatorios están marcados con un asterisco (*).


¿Necesita un IBM ID?
¿Olvidó su IBM ID?


¿Olvidó su Password?
Cambie su Password

Al hacer clic en Enviar, usted está de acuerdo con los términos y condiciones de developerWorks.

 


La primera vez que inicie sesión en developerWorks, se creará un perfil para usted. La información en su propio perfil (nombre, país/región y nombre de la empresa) se muestra al público y acompañará a cualquier contenido que publique, a menos que opte por la opción de ocultar el nombre de su empresa. Puede actualizar su cuenta de IBM en cualquier momento.

Toda la información enviada es segura.

Elija su nombre para mostrar



La primera vez que inicia sesión en developerWorks se crea un perfil para usted, teniendo que elegir un nombre para mostrar en el mismo. Este nombre acompañará el contenido que usted publique en developerWorks.

Por favor elija un nombre de 3 - 31 caracteres. Su nombre de usuario debe ser único en la comunidad developerWorks y debe ser distinto a su dirección de email por motivos de privacidad.

Los campos obligatorios están marcados con un asterisco (*).

(Por favor elija un nombre de 3 - 31 caracteres.)

Al hacer clic en Enviar, usted está de acuerdo con los términos y condiciones de developerWorks.

 


Toda la información enviada es segura.


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=90
Zone=Linux
ArticleID=499730
ArticleTitle=Aprenda Linux, 101: Corrientes, tuberías y redirecciones
publish-date=07082010