$ ls *mp3 | xargs mplayer
Playing Lemon.
File not found: 'Lemon'
Playing Tree.mp3.
File not found: 'Tree.mp3'
Exiting... (End of file)
Mi comando falla porque el archivo "Lemon Tree.mp3" contiene espacios y por eso xargs piensa que son dos archivos. ¿Puedo hacer find + xargs trabajar con nombres de archivo como este?
La utilidad xargs lee cadenas delimitadas por espacios, tabuladores, nuevas líneas y fin de archivo de la entrada estándar y ejecuta la utilidad con las cadenas como argumentos.
Usted quiere evitar el uso del espacio como delimitador. Esto se puede hacer cambiando el delimitador para xargs. Según el manual:
-0 Cambie xargs para que espere caracteres NUL (``\0'') como separadores, en lugar de espacios y nuevas líneas. Se espera que esto se use en concierto con la función -print0 en find(1).
Por ejemplo:
find . -name "*.mp3" -print0 | xargs -0 mplayer
Para responder a la pregunta sobre la reproducción del séptimo mp3; es más sencillo ejecutar
mplayer "$(ls *.mp3 | sed -n 7p)"
Pruebe
find . -name \*.mp3 -print0 | xargs -0 mplayer
en lugar de
ls | grep mp3
Depende de (a) lo apegado que esté al número 7 en comparación con, digamos, Limones, y (b) si alguno de sus nombres de archivo contiene nuevas líneas (y si está dispuesto a renombrarlos en caso afirmativo).
Hay muchas formas de solucionarlo, pero algunas de ellas son:
mplayer Lemon*.mp3
find . -name 'Lemon*.mp3' -exec mplayer {} ';'
i=0
for mp3 in *.mp3
do
i=$((i+1))
[ $i = 7 ] && mplayer "$mp3"
done
for mp3 in *.mp3
do
case "$mp3" in
(Lemon*) mplayer "$mp3";;
esac
done
i=0
find . -name *.mp3 |
while read mp3
do
i=$((i+1))
[ $i = 7 ] && mplayer "$mp3"
done
El bucle read
no funciona si los nombres de archivo contienen nuevas líneas; los otros funcionan correctamente incluso con nuevas líneas en los nombres (y mucho menos espacios). En mi opinión, si tiene nombres de archivo que contienen una nueva línea, debería renombrar el archivo sin la nueva línea. El uso de las comillas dobles alrededor del nombre del archivo es clave para que los bucles funcionen correctamente.
Si tiene GNU find
y GNU xargs
(o FreeBSD (*BSD?), o Mac OS X), también puede usar las opciones -print0
y -0
, como en:
find . -name 'Lemon*.mp3' -print0 | xargs -0 mplayer
Esto funciona independientemente del contenido del nombre (los dos únicos caracteres que no pueden aparecer en un nombre de archivo son la barra y NUL, y la barra no causa problemas en una ruta de archivo, por lo que usar NUL como delimitador del nombre lo cubre todo). Sin embargo, si necesitas filtrar las 6 primeras entradas, necesitas un programa que maneje 'líneas' terminadas por NUL en lugar de por newline...y no estoy seguro de que exista alguno.
El primero es de lejos el más sencillo para el caso concreto que nos ocupa; sin embargo, puede que no sea generalizable para cubrir tus otros escenarios que aún no has enumerado.