L'output di ls ha nuove righe ma viene visualizzato su una sola riga. Perché?


41

Penso che potrei trascurare un punto relativamente fondamentale per quanto riguarda la shell. L'output del comando ls per impostazione predefinita separa l'output con le nuove righe, ma la shell visualizza l'output su una sola riga.

Qualcuno può spiegarmi questo? Avevo sempre presunto che l'output fosse semplicemente separato da spazi, ma ora che vedo l'output separato da newline, mi aspetto che l'output venga visualizzato su righe separate.

Esempio:

cpoweradm@debian:~/lpi103-4$ ls text*
text1  text2  text3

od mostra che l'output è separato da newline:

cpoweradm@debian:~/lpi103-4$ ls text* | od -c
0000000   t   e   x   t   1  \n   t   e   x   t   2  \n   t   e   x   t
0000020   3  \n
0000022

Se sono presenti newline, perché l'output non viene visualizzato come:

text1 
text2
text3

Risposte:


44

Quando si esegue il pipe dell'output, lsagisce in modo diverso.

Questo fatto è nascosto nella documentazione informativa :

Se l'output standard è un terminale, l'output è in colonne (ordinate verticalmente) e i caratteri di controllo vengono emessi come punti interrogativi; in caso contrario, l'output viene elencato uno per riga e i caratteri di controllo vengono emessi così come sono.

Per provarlo, prova a correre

ls

e poi

ls | less

Ciò significa che se si desidera garantire che l'output sia un file per riga, indipendentemente dal fatto che venga reindirizzato o reindirizzato, è necessario eseguire

ls -1

( -1è il numero uno)

In alternativa, è possibile forzare ls | lessl'output in colonne eseguendo

ls -C

( -Cè una C maiuscola)


6
@theconnorpower: è praticamente specifico per ls. È utile, ma è chiaramente incoerente e sorprendente. Si noti tuttavia che alcuni comandi che producono output colorati rimuoveranno i colori anche quando vengono convogliati.
Mikel

5
@theconnorpower: Curiosità: gli inventori di Unix hanno continuato a scrivere Plan9. In Plan9, lsstampa sempre uno per riga e lcstampa sempre in colonne.
Mikel

2
@theconnorpower: ci sono anche programmi che leggono le dimensioni del terminale e regolano di conseguenza il loro output, per esempio su Debian dpkg -lutilizzerà l'intera larghezza dello schermo, ma se sta stampando su una pipe, si presume che il terminale sia largo 80 colonne e abbrevia l'output per adattarlo, se necessario.
Mikel

1
@Mikel Interessante ascoltare le differenze ls / lc in Plan9. Grazie per la risposta dettagliata
zod90,

1
Come può un programma determinare se il suo output viene reindirizzato a un file o se sta andando a una shell?
user2820379

4

La tua scoperta evidenzia il motivo principale per cui analizzare l'output di lsè sempre una cattiva idea. Vedi la wiki di Greg per una spiegazione completa .

Pensa al tuo problema al contrario. Hai notato che a volte lo fa e talvolta non stampa nuove righe tra l'output. Per l'uso negli script o quando è forzato dalla -1bandiera, lo fa. Una nuova riga alla fine di ogni file. Cosa non è garantito che ogni nuova riga rappresenti un nuovo nome di file . In effetti, se un nome file contiene una nuova riga stessa, l'output di ls sarà assolutamente non analizzabile. Considera questi nomi di file:

file1
file2\nfile3
file4

Quando hai ls -1una directory con quella dentro, otterrai qualcosa che assomiglia a questo:

file1
file2
file3
file4

Non pensi che ci fossero naturalmente quattro file? Così sarebbe qualsiasi script che analizza l'output di ls. In realtà ci sono tre file, uno dei quali con un nome difficile, ma non saresti in grado di capirlo dall'output di ls. *

* A meno che tu non stia usando la -lbandiera e noti che l'output è stato interrotto, ma i tuoi script sarebbero ancora soffocati.


3
Se devi davvero analizzare l'output di ls, l' -bopzione può aiutarti. Trasforma la newline in \n, ecc.
Mikel
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.