Considere las dos muestras de concha
$ ls
myDoc.html
SomeDirectory
someDoc.txt
y
$ echo $(ls)
myDoc.html SomeDirectory someDoc.txt
El primero se ejecuta ls
y, según tengo entendido, agrega el contenido del directorio de trabajo actual al stdout
archivo (que es lo que muestra el terminal). ¿Es esto correcto?
El segundo toma el valor del ls
comando (lo que significa que es el contenido del directorio de trabajo actual) y lo imprime en el stdout
archivo. ¿Es esto correcto?
¿Por qué los dos comandos dan diferentes salidas?
ls
por sí solo no le da múltiples artículos por línea?echo *
?Respuestas:
Cuando ejecutas este comando:
el terminal muestra la salida de
ls
.Cuando ejecutas este comando:
el shell captura la salida
$(ls)
y realiza la división de palabras en él. Con el valor predeterminadoIFS
, esto significa que todas las secuencias de espacios en blanco, incluidos los caracteres de nueva línea, se reemplazan por un solo espacio en blanco. Es por eso que la salida deecho $(ls)
aparece en una línea.Para una discusión avanzada sobre la división de palabras, vea las preguntas frecuentes de Greg .
Suprimir la división de palabras
El shell no realiza la división de palabras en cadenas entre comillas. Por lo tanto, puede suprimir la división de palabras y retener la salida multilínea con:
ls
y salida multilíneaEs posible que haya notado que a
ls
veces imprime más de un archivo por línea:Este es el valor predeterminado cuando la salida de
ls
va a un terminal. Cuando la salida no va directamente a una terminal,ls
cambia su valor predeterminado a un archivo por línea:Este comportamiento está documentado en
man ls
.Otra sutileza: sustitución de comandos y líneas nuevas
$(...)
es la sustitución de comandos y el shell elimina los caracteres de línea nueva del resultado de la sustitución de comandos . Esto normalmente no se nota porque, por defecto,echo
agrega una nueva línea al final de su salida. Por lo tanto, si pierde una nueva línea desde el final$(...)
y gana unaecho
, no hay cambio. Sin embargo, si la salida de su comando termina con 2 o más caracteres de nueva línea yecho
agrega solo uno, a su salida le faltarán una o más nuevas líneas. Como ejemplo, podemos usarprintf
para generar caracteres de nueva línea finales. Tenga en cuenta que los dos comandos siguientes, a pesar del número diferente de líneas nuevas, producen el mismo resultado de una línea en blanco:Este comportamiento está documentado en
man bash
.Otra sorpresa: expansión del nombre de ruta, dos veces
Vamos a crear tres archivos:
Observe la diferencia entre
ls file?
yecho $(ls file?)
:En el caso de
echo $(ls file?)
la glob archivofile?
se expande en dos ocasiones , haciendo que los nombres de archivofile1
yfile2
de aparecer dos veces en la salida. Esto se debe a que, como señala Jeffiekins, la expansión del nombre de ruta se realiza primero por el shell antes dels
ejecutarse y luego nuevamente antes deecho
ejecutarse.La segunda expansión del nombre de ruta se puede suprimir si usamos comillas dobles:
fuente
isatty
puede verificar si stdout es un tty, ls usa esto para determinar si usar colores o no.$( )
realidad proporciona una barrera de sintaxis para que no necesite interpolar?$()
proporciona una barrera de sintaxis.echo
comando expandirá el comodín . Por ejemplo, sils
devuelve el archivo? file1 file2 , entoncesecho $(ls)
devolverá el archivo? archivo1 archivo2 archivo1 archivo2 .echo
no expande comodines; el shell lo hace antes de pasar la expansión resultante como argumentos aecho
.ls
sabe si está enviando salida a un terminal o no.Ejecutar
ls
en un símbolo del sistema escribirá en su pseudo-tty. Redirigir la salida dels
generalmente no irá a un pseudo-tty, yls
formateará la salida de manera diferente.fuente