czy potok ls jest taki sam jak ls -1?

19

lszwraca dane wyjściowe w kilku kolumnach, podczas gdy ls|catzwraca dane identyczne z bajtami ls -1dla katalogów, które próbowałem. Nadal widzę wiele ls -1odpowiedzi ls -1|wc -l. Czy jest jakiś powód, aby preferować ls -1? Dlaczego ...|catzmienia wyjście ls?

rubystallion
źródło
1
nazwy plików mogą zawierać znaki nowej linii, więc policzyłbyś je kilka razy ... zamiast tego możesz posix zrobić: n=0; for i in .* *; do ((n++)) ; done ; echo $n(upuść. *, jeśli nie chcesz liczyć tych). lub: ls -1d ./.* ./* | grep '^\./' | wc -l (ponieważ nazwy plików nie mogą zawierać „/”)
Olivier Dulac
3
lsdane wyjściowe na terminalu zwykle domyślnie zawierają kody kolorów. W przypadku danych wyjściowych do terminala kolor jest zazwyczaj domyślnie wyłączony. W GNU jest to --color={always,auto,never}IIRC. Jeśli kolor jest zawarty w jednym, ale nie w innym, wówczas wyniki mogą wyglądać identycznie na ekranie, ale nie są identyczne bajtowo (kody kolorów stanowią część wyniku ls).
CVn
@ MichaelKjörling Myślę, że powinieneś napisać to jako odpowiedź.
200_success
@ MichaelKjörling To coś interesującego, czego nie rozważałem. Czy istnieje ogólny sposób na zawsze przesyłanie potokowe tak, jakby dane wyjściowe były wysyłane do terminalu bez konieczności zapamiętywania opcji terminalu dla wyjścia kolorów i kolumn itp.?
rubystallion,
@rubystallion To brzmi jak dobre osobne pytanie.
CVn

Odpowiedzi:

26

lssprawdza, czy wyjście trafia do terminala. Jeśli dane wyjściowe nie trafiają do terminala, to -1jest to ustawienie domyślne. (To może być zmieniona przez jednego z -C, -mlub -xopcji).

Tak więc, gdy lsjest używany w potoku i nie zastąpiłeś go inną opcją, lsużyje -1. Możesz na tym polegać, ponieważ takie zachowanie jest wymagane przez POSIX

Specyfikacja POSIX

POSIX wymaga -1domyślnie, gdy dane wyjściowe nie trafiają do terminala:

Specyfikacja POSIX :

Domyślnym formatem jest wypisanie jednego wpisu w wierszu na standardowe wyjście; wyjątki dotyczą terminali lub gdy podano jedną z opcji -C, -m lub -x. Jeśli dane wyjściowe dotyczą terminala, format jest zdefiniowany w implementacji.

Te trzy opcje, które zastępują domyślny format jednokolumnowy to:

-C
Napisz wielotekstowy wynik z kolumn posortowanych według kolumn, zgodnie z kolejnością zestawiania. Liczba kolumn tekstowych i znaki separatora kolumn są nieokreślone, ale należy je dostosować do charakteru urządzenia wyjściowego. Ta opcja wyłącza wyjście w długim formacie.

-m
Format wyjściowy strumienia; wypisz nazwy ścieżek na całej stronie, oddzielone znakiem <comma>, a następnie znakiem <space>. Użyj znaku <nowa linia> jako terminatora listy i po sekwencji separatora, gdy w linii nie ma miejsca na następny wpis na liście. Ta opcja wyłącza wyjście w długim formacie.

-x
Taki sam jak -C, z wyjątkiem tego, że dane wyjściowe z wielu kolumn tekstowych są tworzone z wpisami posortowanymi w poprzek kolumn, a nie w dół, w kolumnach. Ta opcja wyłącza wyjście w długim formacie.

Dokumentacja GNU

Z podręcznika GNU ls :

„-1”
--format = pojedyncza kolumna ”Wyświetla
jeden plik w wierszu. Jest to ustawienie domyślne dla ls, gdy standardowe wyjście nie jest terminalem . Zobacz także opcje -b i -q, aby ukryć bezpośrednie wyświetlanie znaków nowego wiersza w nazwie pliku. [Podkreślenie dodane]

Przykłady

Utwórzmy trzy pliki:

$ touch file{1..3}

Gdy dane wyjściowe trafiają do terminala, GNU lsdecyduje się na użycie formatu wielokolumnowego:

$ ls
file1  file2  file3

Gdy dane wyjściowe trafiają do potoku, specyfikacja POSIX wymaga, aby domyślna była jedna kolumna:

$ ls | cat
file1
file2
file3

Trzy wyjątki, które zastępują domyślne zachowanie -mdla pojedynczej kolumny, dotyczą rozdzielania przecinkiem, -Csortowania kolumn i -xsortowania według kolumn:

$ ls -m | cat
file1, file2, file3
$ ls -C | cat
file1  file2  file3
$ ls -x | cat
file1  file2  file3
John1024
źródło
„POSIX wymaga wartości domyślnej -1, gdy dane wyjściowe trafiają do terminala:” ... ale cytat wskazuje, że wymaga -1wartości domyślnej, z wyjątkiem sytuacji, gdy dane wyjściowe trafiają do terminala (lub innych warunków)
muru
@muru Dzięki za złapanie tego! Odpowiedź zaktualizowana.
John1024,
Każda chmura ma srebrną podszewkę. Ponieważ Twoja odpowiedź została zaakceptowana, zanim moja została opublikowana, dostałem funky kapelusz do pizzy!
G-Man mówi „Przywróć Monikę”
@ G-Man Bardzo dobrze. I to jest przystojny kapelusz!
John1024,
9
  • Dlaczego potokowanie standardowego wyjścia zmienia zachowanie ls? Ponieważ tak zostało zaprojektowane. POSIX Specyfikacja mówi:

    Domyślnym formatem jest wypisanie jednego wpisu w wierszu na standardowe wyjście; Wyjątkami są do zacisków lub gdy jeden z -C, -mlub -xjest określony opcji. Jeśli dane wyjściowe dotyczą terminala, format jest zdefiniowany w implementacji.

    co jest w rzeczywistości dwuznaczne co do domyślnego zachowania (gdy nie jest określone przez opcję taką jak -llub -1) z wyjściem do terminala, a dokumentacja GNU Coreutils mówi

    Jeśli standardowym wyjściem jest terminal, dane wyjściowe są w kolumnach (posortowane pionowo), a znaki sterujące są wyprowadzane jako znaki zapytania; w przeciwnym razie dane wyjściowe są wyświetlane po jednym w wierszu, a znaki sterujące są wyświetlane w niezmienionej postaci.

    Możesz więc zobaczyć, że wyjście do pliku będzie działało tak samo jak wyjście do potoku; to jest jeden wpis w wierszu, tak jakby -1został określony.

  • Dlaczego został tak zaprojektowany? To może nie być pewne (chyba że ktoś znajdzie jakieś uwagi do projektu), ale myślę:
    • Kiedy lspisze do terminala, oczekuje, że człowiek patrzy na wynik. Ludzie wolą otrzymywać informacje w minimalnej niezbędnej liczbie wierszy, aby rzeczy nie przewijały się na ekranie.
    • Kiedy lspisze do potoku, oczekuje, że inny program odczyta dane wyjściowe. O wiele łatwiej jest programowi odczytać dane, które mają jedną wartość w wierszu, niż próbować parsować kolumny (ponieważ nazwy plików mogą zawierać spacje).
  • Czy jest jakiś powód, aby preferować ls -1 pisanie do pliku lub potoku? Nie.
G-Man mówi „Przywróć Monikę”
źródło
-4

Podczas potokowania ls, ls nie może określić, ile kolumn faktycznie ma konsola (niezależnie od polecenia po prawej stronie). Czyni to po prostu według własnego wyboru, czyli innymi słowy, takie jest zachowanie niestabilne i może ulec zmianie w przyszłych wersjach.

Natomiast ls -1został stworzony w celu zliczania lub pisania skryptów, więc jego zachowanie jest stabilne.

Xanoetux
źródło
9
Jak inne odpowiedzi mówią, że takie zachowanie jest wymagane przez POSIX, więc nazwanie go niestabilnym jest błędne.
Henrik - przestań krzywdzić Monikę