Wiem, że cat
mogę to zrobić, ale jego głównym celem jest konkatenacja, a nie tylko wyświetlanie treści.
Wiem też, o less
, a more
, ale szukam czegoś prostego ( nie pager ), które po prostu wyprowadza zawartość pliku do terminalu i jest zrobiona specjalnie dla tego, jeśli nie ma czegoś takiego.
cat
konkatenuje.a+b+c
wymaga 2 dodawania, a przetwarzaniea
nie wymaga dodawania niczego. Podobnie wykonywaniecat f
nie wiąże się z niczym (nawet jeśli jest to jedyna rzecz, którą może oznaczać „łączenie sekwencji jednego pliku”).cat
czyta plik i zapisuje inny plik (strumień), ale to nie znaczy, że wszystko łączy. Jeśli masz na myśli, żecat f
tak naprawdę jestcat - f
, to po prostu nieprawda.cat
naprawdę miał na celu konkatenację (cat file1 file2
połączy oba pliki do standardowego wyjścia). Ale jego efektem ubocznym jest to, że mając tylko 1 plik jako argument, wysyła ten jeden plik do standardowego wyjścia (gdziekolwiek to się dzieje, albo terminal, albo przekierowuje do czegoś). Nie było więc żadnego innego polecenia stworzonego tylko do wyjścia na standardowe wyjście, ponieważcat
istniało i pozwalało na to po prostu. Dlatego chcesz użyćcat
.Odpowiedzi:
Najbardziej oczywistym z nich jest
cat
. Ale spójrz także nahead
itail
. Istnieją także inne utillities powłoki do wydrukowania pliku linia po linii:sed
,awk
,grep
. Ale mają one na przemian zawartość pliku lub wyszukiwanie w pliku.Zrobiłem kilka testów, aby oszacować, który jest najbardziej skuteczny. Przeglądam wszystkie koryta,
strace
aby zobaczyć, które wywołały najmniej wywołań systemowych. Mój plik ma 1275 linii.awk
: 1355 wywołań systemowychcat
: 51 wywołań systemowychgrep
: 1337 wywołań systemowychhead
: 93 wywołań systemowychtail
: 130 wywołań systemowychsed
: 1378 wywołań systemowychJak widać, nawet jeśli
cat
został zaprojektowany do łączenia plików, jest najszybszy i najskuteczniejszy.sed
,awk
Agrep
wydrukowane pliku wiersz po wierszu, to dlatego, że mają więcej niż 1275 wywołań systemowych.źródło
Celem
cat
jest właśnie to, odczytanie pliku i wyjście na standardowe wyjście.źródło
cat --help
mówi „Połącz pliki lub standardowe wejście do standardowego wyjścia”. Nie chcę niczego konkatenowaćreadlink /dev/fd/1
na przykład - powinieneś dostać tam nazwę swojego tty, jeśli uruchamiasz się w standardowym monicie. Więc łączenie danych wejściowych i wyjściowych jest tym, o co prosisz.Najpierw
cat
zapisuje na standardowe wyjście, które niekoniecznie jest terminalem, nawet jeślicat
zostało wpisane jako część polecenia do interaktywnej powłoki. Jeśli naprawdę potrzebujesz czegoś do zapisania na terminalu, nawet gdy przekierowane jest standardowe wyjście, nie jest to takie łatwe (musisz określić, który terminal, a może nawet nie być, jeśli polecenie zostanie wykonane ze skryptu), chociaż jeden mógłby (ab) użyć standardowego wyjścia błędu, jeśli polecenie jest tylko częścią potoku. Ale skoro wskazałeś, że tocat
rzeczywiście działa, przypuszczam, że nie pytałeś o taką sytuację.Jeśli Twoim celem byłoby przesłanie tego, co zapisano na standardowe wyjście do potoku, wówczas użycie
cat
będzie kwalifikować się do nagrody Bezużyteczne użycie kota , ponieważcat file | pipeline
(gdziepipeline
oznacza dowolny potok) można to zrobić bardziej efektywnie<file pipeline
. Ale znowu, z twoich sformułowań wywnioskuję, że to nie była twoja intencja.Więc nie jest tak jasne, o co się martwisz. Jeśli nie możesz
cat
pisać, możesz zdefiniować alias jedno- lub dwuznakowy (wciąż istnieje kilka takich nazw, które nie są używane w standardowym Uniksie). Jeśli jednak martwisz się, żecat
spędzasz bezużyteczne cykle, nie powinieneś.Gdyby istniał program,
null
który nie przyjmuje żadnych argumentów i po prostu kopiuje standardowe wejście na standardowe wyjście (obiekt neutralny dla potoków), możesz zrobić to, co chcesz<file null
. Nie ma takiego programu, chociaż napisanie go byłoby łatwe (program C zmain
funkcją tylko jednego wiersza może wykonać zadanie), ale wywoływaniecat
bez argumentów (lubcat -
jeśli chcesz być jawny) robi właśnie to.Jeśli istniał
nocat
program, który pobiera dokładnie jeden argument nazwy pliku, próbuje otworzyć plik, narzeka, jeśli nie może, a w przeciwnym razie kontynuuje kopiowanie z pliku na standardowe wyjście, to właśnie o to prosisz. Jest to tylko nieco trudniejsze do napisania niżnull
, ponieważ główną pracą jest otwieranie pliku, testowanie i być może narzekanie (jeśli jesteś skrupulatny, możesz również chcieć dołączyć test, który zawiera dokładnie jeden argument, i narzekać inaczej). Ale znowucat
, teraz wyposażony w pojedynczy argument, robi właśnie to, więc nie ma potrzeby żadnegonocat
programu.Po napisaniu
nocat
programu, po co zatrzymywać się na jednym argumencie? Zawijanie kodu w pętlęfor(;*argp!=NULL;++argp)
wcale nie stanowi żadnego wysiłku, dodaje do pliku binarnego co najwyżej kilka instrukcji maszynowych i pozwala uniknąć narzekania na niewłaściwą liczbę argumentów (co oszczędza znacznie więcej instrukcji). Voilà prymitywna wersjacat
łączenia plików. (Szczerze mówiąc, musisz go trochę ulepszyć, aby bez argumentów zachowywał się jaknull
.)Oczywiście w prawdziwym
cat
programie dodali kilka dzwonków i gwizdków, ponieważ zawsze tak robią. Ale istotą jest to, że aspekt „konkatenacji”cat
kosztów naprawdę nie wymaga żadnego wysiłku, ani dla programisty, ani dla maszyny, która go wykonuje. Fakt, którycat
pochłanianull
inocat
wyjaśnia nieistnienie takich programów. Unikaj używaniacat
z jednym argumentem, jeśli wynik trafia do potoku, ale jeśli jest on używany tylko do wyświetlania zawartości pliku w terminalu, nawet strona, do której dowiązałem, przyznaje, że jest to użyteczne zastosowaniecat
, więc nie wahaj się.Możesz przetestować, który
cat
jest naprawdę zaimplementowany przez prostą pętlę wokół hipotetycznejnocat
funkcjonalności, wywołująccat
kilka nazw plików, wśród których jedna jest niepoprawna, a nie na pierwszej pozycji: zamiast narzekać od razu, że ten plik nie istnieje,cat
najpierw zrzuca poprzedzające go prawidłowe pliki, a następnie narzeka na nieprawidłowy plik (przynajmniej tak zachowuje się mój kot).źródło
W trakcie
zsh
próbyUważam, że to najkrótszy sposób na wydrukowanie pliku. Używa „ukrytego”
cat
(lubmore
jeśli stdout jest terminalem), ale polecenie użyte do drukowania jest kontrolowane przezREADNULLCMD
zmienną, którą można bezpiecznie zastąpić bezpośrednio nazwą polecenia lub nawet jakąś funkcją. Na przykład, aby wydrukować pliki z numeracją linii:źródło
POSIX definiuje cat jako:
Więc myślę, że konkatenacja tutaj oznacza odczytywanie plików w sekwencji .
źródło
Wiem, że to jest pytanie z przeszłości. Technicznie, ponieważ drukowanie zawartości pliku
stdout
jest formą konkatenacji,cat
jest semantycznie właściwe. Nie zapominaj, żeprintf
semantycznie ma na celu formatowanie i drukowanie danych. Bash zapewnia również składnię przekierowującą dane wejściowe i wyjściowe z plików. Ich połączenie może powodować:źródło
cat file.txt
, ponieważ usuwa wszelkie końcowe znaki nowej linii ($(...)
robi to).Korzystanie z
bash
wbudowanych funkcji i unikanie tworzenia podprocesów:IFS
zostaną zastosowane tylko doread
poleceń, więc nie martw się o swoje globalneIFS
zmiany.Pętla wymagana do obsługi znaków zerowych (dzięki Stéphane Chazelas).
Ten sposób nie jest odpowiedni dla dużych plików, ponieważ zawartość pliku najpierw odczytuje zmienną (czyli pamięć). BTW Próbowałem wydrukować plik tekstowy 39M w ten sposób, a użycie pamięci bash nie przekroczyło 5M, więc nie jestem pewien co do tego przypadku.
Jest również cholernie wolny i nieefektywny procesorowo: dla tego samego pliku 39M zajęło ~ 3 minuty przy 100% wykorzystaniu pojedynczego rdzenia.
W przypadku dużych plików lub plików binarnych lepiej użyć
cat '/path/to/file'
lub nawet,dd if='/path/to/file' bs=1M
jeśli to możliwe.źródło
pv -q
które w systemie Linux mogą używać,splice()
które dla niektórych typów stdin / stdout poprawią wydajność.Możesz to zrobić tylko jako demonstrację
źródło