¿se canaliza ls igual que ls -1?

19

lsdevuelve resultados en varias columnas, mientras que ls|catdevuelve resultados idénticos en bytes con los ls -1directorios que he probado. Todavía veo ls -1respuestas entubados, como ls -1|wc -l. ¿Hay alguna razón para preferir ls -1? ¿Por qué ...|catcambia la salida de ls?

rubystallion
fuente
1
los nombres de archivo pueden contener nuevas líneas, por lo que podría contarlas varias veces ... en su lugar, podría hacerlo: n=0; for i in .* *; do ((n++)) ; done ; echo $n(suelte el. * si no desea contarlas). o: ls -1d ./.* ./* | grep '^\./' | wc -l (como los nombres de archivo no pueden contener '/')
Olivier Dulac
3
lsLa salida a un terminal comúnmente incluye códigos de color por defecto. Para la salida a un no terminal, el color generalmente está deshabilitado de forma predeterminada. En GNU, eso es --color={always,auto,never}IIRC. Si el color se incluye en uno pero no en otro, entonces las salidas pueden aparecer idénticas en la pantalla, pero no son idénticas en bytes (los códigos de color forman parte de la salida de ls).
un CVn
@ MichaelKjörling Creo que deberías escribir eso como respuesta.
200_success
@ MichaelKjörling Eso es algo interesante que no he considerado. ¿Existe una forma general de canalizar siempre como si se emitiera a la terminal sin tener que recordar las opciones de terminal para la salida de color y columna, etc.?
rubystallion
@rubystallion Eso suena como una buena pregunta por separado.
un CVn

Respuestas:

26

lsprueba si la salida va a una terminal. Si la salida no va a una terminal, entonces -1es la predeterminada. (Esto se puede anular por uno de los -C, -mo -xlas opciones).

Por lo tanto, cuando lsse usa en una tubería y no lo ha anulado con otra opción, lslo usará -1. Puede confiar en esto porque POSIX requiere este comportamiento

Especificación POSIX

POSIX requiere -1como valor predeterminado cada vez que la salida no va a una terminal:

La especificación POSIX :

El formato predeterminado será enumerar una entrada por línea a la salida estándar; las excepciones son a terminales o cuando se especifica una de las opciones -C, -m o -x. Si la salida es a una terminal, el formato está definido por la implementación.

Estas tres opciones que anulan el formato predeterminado de una sola columna son:

-C
Escribir salida de columna de texto múltiple con entradas ordenadas por columnas, de acuerdo con la secuencia de clasificación. El número de columnas de texto y los caracteres separadores de columna no están especificados, pero deben adaptarse a la naturaleza del dispositivo de salida. Esta opción deshabilita la salida de formato largo.

-m
Formato de salida de flujo; enumere los nombres de ruta en la página, separados por un carácter <comma> seguido de un carácter <space>. Utilice un carácter <línea nueva> como terminador de la lista y después de la secuencia del separador cuando no haya espacio en una línea para la siguiente entrada de la lista. Esta opción deshabilita la salida de formato largo.

-x
Lo mismo que -C, excepto que la salida de columnas de texto múltiple se produce con entradas clasificadas en las columnas, en lugar de hacia abajo. Esta opción deshabilita la salida de formato largo.

Documentación de GNU

Del manual de GNU ls :

'-1'
'--format = single-column'
Lista un archivo por línea. Este es el valor predeterminado para ls cuando la salida estándar no es una terminal . Consulte también las opciones -b y -q para suprimir la salida directa de caracteres de nueva línea dentro de un nombre de archivo. [Énfasis añadido]

Ejemplos

Vamos a crear tres archivos:

$ touch file{1..3}

Cuando la salida va a una terminal, GNU lselige usar un formato de múltiples columnas:

$ ls
file1  file2  file3

Cuando la salida se dirige a una tubería, la especificación POSIX requiere que la columna única sea la predeterminada:

$ ls | cat
file1
file2
file3

Las tres excepciones que anulan el comportamiento predeterminado de una sola columna son -mlas separadas por comas, las -Ccolumnas ordenadas y las -xcolumnas ordenadas:

$ ls -m | cat
file1, file2, file3
$ ls -C | cat
file1  file2  file3
$ ls -x | cat
file1  file2  file3
John1024
fuente
"POSIX requiere -1 como valor predeterminado cuando la salida va a un terminal:" ... pero la cita indica que requiere -1como valor predeterminado, excepto cuando la salida va al terminal (u otras condiciones)
muru
@muru ¡Gracias por atrapar eso! Respuesta actualizada
John1024
Bueno, cada nube tiene un lado positivo. Debido a que su respuesta fue aceptada antes de que se publicara la mía, ¡obtuve un sombrero de pizza funky!
G-Man dice 'Restablecer a Monica' el
@ G-Man Muy bien. ¡Y qué hermoso sombrero es!
John1024
9
  • ¿Por qué la tubería de la salida estándar cambia el comportamiento de ls? Porque fue diseñado de esa manera. La especificación POSIX dice:

    El formato predeterminado será enumerar una entrada por línea a la salida estándar; las excepciones son para terminales o cuando uno de los -C, -mo -xse especifica opciones. Si la salida es a una terminal, el formato está definido por la implementación.

    que en realidad es ambiguo sobre el comportamiento predeterminado (cuando no está especificado por una opción como -lo -1) con salida a una terminal, y la documentación de GNU Coreutils dice

    Si la salida estándar es una terminal, la salida está en columnas (ordenadas verticalmente) y los caracteres de control se muestran como signos de interrogación; de lo contrario, la salida aparece una por línea y los caracteres de control se muestran tal cual.

    Entonces puede ver que la salida a un archivo actuará igual que la salida a una tubería; es decir, una entrada por línea, como si se -1hubiera especificado.

  • ¿Por qué fue diseñado de esa manera? Puede que no sea posible saberlo con seguridad (a menos que alguien pueda encontrar algunas notas de diseño), pero supongo:
    • Cuando lsestá escribiendo en una terminal, espera que un ser humano esté mirando la salida. La gente preferirá obtener información en el número mínimo necesario de líneas, por lo que las cosas no se desplazan de la pantalla.
    • Cuando lsescribe en una tubería, espera que otro programa esté leyendo la salida. Es mucho más fácil para un programa leer datos que son un valor por línea que tratar de analizar columnas (ya que los nombres de archivo pueden contener espacios).
  • ¿Hay alguna razón para preferir ls -1 cuando estás escribiendo en un archivo o una tubería? No.
G-Man dice 'restablecer a Monica'
fuente
-4

Al canalizar ls, ls no puede determinar cuántas columnas tiene realmente la consola (independientemente del comando del lado derecho). Entonces, lo hace por su propia elección o, en otras palabras, este comportamiento es inestable y puede cambiar en futuras versiones.

Por el contrario, ls -1se creó con el propósito de contar o crear scripts en general, por lo que su comportamiento es estable.

xanoetux
fuente
99
Como las otras respuestas dicen que POSIX requiere este comportamiento, llamarlo inestable es incorrecto.
Henrik - deja de lastimar a Monica el