2013-08-01 7 views
13

Tak, zawsze miałem wątpliwości, jak przekierowanie działa w następujących sytuacjach:Dlaczego symbol przekierowania zmienia zachowanie ls?

  1. wpisuję „ls”, a wszystkie nazwy plików są oddzielone białymi spacjami:

    test$ touch a b c 
    test$ ls 
    a b c 
    
  2. używam a ">" przekierować STDOUT do pliku:

    test$ ls > ls.txt 
    test$ cat ls.txt 
    a 
    b 
    c 
    ls.txt 
    

To ja Interesujące jest to, że format zmienia się, a nazwy plików są oddzielone znakami nowego wiersza. Wydaje się, że dane wyjściowe generowane są przez ls -1.

Dlaczego dane wyjściowe w tym drugim przypadku różnią się od danych wyjściowych w poprzednim przypadku? Czy ls może zobaczyć symbol ">", aby zmienić jego zachowanie?

+0

Doskonałe pytanie. Miliony ludzi używają 'ls' od lat i zastanawiają się nad tym samym. –

+0

Jeśli * chcesz * kolumny w przekierowanych danych wyjściowych, spróbuj 'ls -C'. –

Odpowiedz

11

ls testuje strumień wyjściowy, aby sprawdzić, czy jest to terminal, i zmienia jego zachowanie w zależności od tego.

To jest udokumentowane; man aktualizacja ls dokumentów kilka rzeczy, które są uzależnione od tego, czy wyjście jest terminal:

  • Jeśli wyjście jest terminal, -C (dla wyjścia multi-kolumna) jest domyślny, w przeciwnym razie -1 (jedna kolumna) jest domyślny.
  • Jeśli użyto -l lub -s, a wyjście jest terminalem, suma wszystkich rozmiarów plików lub bloków jest drukowana na linii przed listingiem.
  • Jeśli wyjście jest terminal, -q jest domyślna. Spowoduje to wyświetlenie znaków nie-graficznych jako "?". W przeciwnym razie wartości domyślne to -v i -w. Jestem nieco niejasne na różnicy pomiędzy -v i -w. Dokumentacja mam mówi -v siły „nieedytowaną drukowanie znaków innych niż graficzne” i -w sił „surowe drukowanie znaków zakaz druku.”
+1

Więc działa przy użyciu [-t 1]? –

+1

Zasadniczo tak. 'ls' używa odpowiednika' [-t 1] ', ale ponieważ' ls' jest napisane w C, a nie sh, używa innej konstrukcji z tą samą semantyką. –

+0

@YuFu Wywołuje funkcję POSIX 'isatty' (od' unistd.h'), co prawdopodobnie jest również tym, co 'test' wywołuje, gdy podana jest flaga' -t'. – sepp2k

3

Nie widać symbol (co jest interpretowane przez powłokę), ale może dowiedzieć się, czy wyjście trafia do terminala.

W celu zorganizowania plików ładnie do kolumn, ls musi znać szerokość terminala. Kiedy urządzenie wyjściowe nie jest terminal, to po prostu nie wie, jak formatować swoje wyjście.

Inną miłą konsekwencją tego zachowania jest to, że można robić rzeczy takie jak ls | wc -l, nie martwiąc się o wiele plików w tej samej linii. (Nadal musisz się martwić nazwami plików zawierającymi znaki nowej linii).

2

ls wykorzystuje zmienną wewnętrzną o nazwie ls_mode, która jest inna w przypadku poleceń typu "type" 3 ls wprowadzanych przez coreuty Gnu. Dla ls, to LS_LS. Dla dir, to LS_MULTI_COL i vdir, to LS_LONG_FORMAT. Rzeczywista wartość ls program wskazuje, że w zależności od tej zmiennej format wyjściowy ulegnie zmianie.Dla ls, to jest to co mówi

Jeśli ls_mode jest LS_LS, format wyjściowy zależy od tego, czy urządzenie wyjściowe jest terminal. To jest dla programu "ls".

Jest to zgodne z Państwa doświadczeniem w zakresie zmiany formatu z lokalizacją wyjściową. Jeśli spróbujesz to samo z dir, to nie będzie tak.

+0

Prawda dla GNU ls, niekoniecznie dla innych programów ls z tym samym zachowaniem. – Vatine

+0

Nie jestem pewien, czy jakiekolwiek inne implementacje 'ls' mają takie zachowanie. Na podstawie tego pytania zakładam, że mówi się o GNU ls. –

+1

IIRC, ls na "Interaktywnym 386/ix" zrobił to samo i to było przed Linuksem, ale nie pre-GNU i najprawdopodobniej * nie * miało GNU ls (będącego tak jak licencjonowanym unixem SysV i wszystkim) . – Vatine

Powiązane problemy