W powłoce, jak mogę tail
najnowszy plik utworzony w katalogu?
linux
shell
shell-script
Itay Moav-Malimovka
źródło
źródło
Odpowiedzi:
Czy nie analizować wyjście ls! Analiza składni ls jest trudna i zawodna .
Jeśli musisz to zrobić, polecam użycie find. Pierwotnie miałem tutaj prosty przykład, aby dać sedno rozwiązania, ale ponieważ ta odpowiedź wydaje się dość popularna, postanowiłem ją poprawić, aby zapewnić wersję, którą można bezpiecznie skopiować / wkleić i używać ze wszystkimi danymi wejściowymi. Czy siedzisz wygodnie? Zaczniemy od oneliner, który da ci najnowszy plik w bieżącym katalogu:
Czyż nie jest to już oneliner? Tutaj znów jest to funkcja powłoki i sformatowana dla łatwiejszego czytania:
I teraz , że jako oneliner:
Jeśli wszystko inne zawiedzie, możesz dołączyć powyższą funkcję do swojego
.bashrc
i rozważyć problem rozwiązany, z jednym zastrzeżeniem. Jeśli chcesz po prostu wykonać zadanie, nie musisz czytać dalej.Zastrzeżenie polega na tym, że nazwa pliku kończąca się na co najmniej jednym nowym wierszu nadal nie będzie
tail
poprawnie przekazywana . Obejście tego problemu jest skomplikowane i uważam za wystarczające, że w przypadku napotkania takiej złośliwej nazwy pliku wystąpi względnie bezpieczne zachowanie błędu „Brak takiego pliku” zamiast czegoś bardziej niebezpiecznego.Soczyste szczegóły
Dla ciekawskich jest to żmudne wyjaśnienie, jak to działa, dlaczego jest bezpieczny i dlaczego inne metody prawdopodobnie nie są.
Niebezpieczeństwo, Will Robinson
Po pierwsze, jedynym bajtem, który można bezpiecznie wytyczyć ścieżki do plików, jest null, ponieważ jest to jedyny bajt powszechnie zabroniony w ścieżkach plików w systemach uniksowych. Ważne jest, aby podczas obsługi dowolnej listy ścieżek plików używać ogranicznika null jako ogranicznika, a także w przypadku przekazywania nawet jednej ścieżki pliku z jednego programu do drugiego, aby robić to w sposób, który nie będzie dławił się na dowolnych bajtach. Istnieje wiele pozornie poprawnych sposobów rozwiązania tego i innych problemów, które zawodzą, zakładając (nawet przypadkowo), że nazwy plików nie będą miały ani nowych linii, ani spacji. Żadne z tych założeń nie jest bezpieczne.
Dla dzisiejszych celów pierwszym krokiem jest uzyskanie listy plików rozdzielonych znakiem null. Jest to dość łatwe, jeśli masz
find
wsparcie-print0
takie jak GNU:Ale ta lista wciąż nie mówi nam, która z nich jest najnowsza, dlatego musimy podać te informacje. Wybieram użycie
-printf
przełącznika find, który pozwala mi określić, jakie dane pojawiają się na wyjściu. Nie wszystkie wersjefind
wsparcia-printf
(to nie jest standardowe), ale GNU find tak. Jeśli znajdziesz się bez niego-printf
, będziesz musiał polegać na tym,-exec stat {} \;
w którym momencie musisz zrezygnować z wszelkiej nadziei na przenośność, co równieżstat
nie jest standardem. Na razie zamierzam przejść dalej, zakładając, że masz narzędzia GNU.Tutaj pytam o format printf,
%T@
czyli czas modyfikacji w sekundach od początku epoki Uniksa, po którym następuje kropka, a następnie liczba wskazująca ułamki sekundy. Dodaję do tego kolejny okres, a następnie%p
(czyli pełną ścieżkę do pliku) przed zakończeniem bajtem zerowym.Teraz mam
Może to być oczywiste, ale ze względu na kompletność
-maxdepth 1
uniemożliwiafind
wyświetlanie zawartości podkatalogów i\! -type d
pomija katalogi, których raczej nie chcesztail
. Do tej pory mam pliki w bieżącym katalogu z informacjami o czasie modyfikacji, więc teraz muszę posortować według czasu modyfikacji.Uzyskiwanie we właściwej kolejności
Domyślnie
sort
oczekuje, że jego dane wejściowe będą rekordami rozdzielanymi znakiem nowej linii. Jeśli masz GNUsort
, możesz poprosić go, aby zamiast tego oczekiwał rekordów rozdzielanych zerami, używając-z
przełącznika .; dla standardusort
nie ma rozwiązania. Interesuje mnie tylko sortowanie według pierwszych dwóch liczb (sekund i ułamków sekundy) i nie chcę sortować według rzeczywistej nazwy pliku, więc mówięsort
dwie rzeczy: po pierwsze, że powinien uwzględniać kropkę (.
) jako ogranicznik pola a po drugie, powinno używać tylko pierwszego i drugiego pola podczas rozważania sposobu sortowania rekordów.Przede wszystkim łączę trzy krótkie opcje, które nie biorą razem żadnej wartości;
-znr
to tylko zwięzły sposób powiedzenia-z -n -r
). Następnie-t .
(spacja jest opcjonalna) podajesort
znak ogranicznika pola i-k 1,2
określa numery pól: pierwszy i drugi (sort
zlicza pola od jednego, a nie zero). Pamiętaj, że przykładowy rekord dla bieżącego katalogu wyglądałby następująco:Oznacza to
sort
, że najpierw przejrzysz,1000000000
a potem0000000000
zamówisz ten rekord. Ta-n
opcja mówisort
o użyciu porównania numerycznego przy porównywaniu tych wartości, ponieważ obie wartości są liczbami. Może to nie być ważne, ponieważ liczby mają ustaloną długość, ale nie szkodzi.Drugi podany przełącznik
sort
służy-r
do „wstecz”. Domyślnie wynikiem sortowania liczbowego będą najpierw liczby najniższe,-r
zmienia się tak, aby wyświetlały najniższe liczby jako ostatnie, a najwyższe jako pierwsze. Ponieważ te liczby są znacznikami czasu wyższe, będą oznaczały nowsze, a to stawia najnowszy rekord na początku listy.Tylko ważne bity
Gdy wyłania się z
sort
niej lista ścieżek do plików, na górze znajduje się żądana odpowiedź, której szukamy. Pozostaje znaleźć sposób na usunięcie innych rekordów i usunięcie znacznika czasu. Niestety nawet GNUhead
itail
nie akceptują przełączników, aby działały na danych rozdzielanych znakiem zerowym. Zamiast tego używam pętli while jako rodzaju biednego człowiekahead
.Najpierw rozbroiłem,
IFS
aby lista plików nie była dzielona na słowa. Następnie powiemread
dwie rzeczy: Nie interpretuj sekwencji ucieczki w input (-r
), a dane wejściowe są rozdzielone bajtem zerowym (-d
); tutaj pusty ciąg''
jest używany do wskazania „no delimiter” aka delimited by null. Każdy rekord zostanie wczytany do zmiennej,record
dzięki czemu przy każdejwhile
iteracji pętli będzie miał jeden znacznik czasu i jedną nazwę pliku. Zauważ, że-d
jest to rozszerzenie GNU; jeśli masz tylko standard,read
ta technika nie zadziała i nie będziesz mieć możliwości skorzystania z niej.Wiemy, że
record
zmienna składa się z trzech części, wszystkie rozdzielone znakami kropki. Za pomocącut
narzędzia można wyodrębnić ich część.Tutaj cały rekord jest przekazywany do
printf
i stamtąd przesyłany docut
; w bashu możesz to jeszcze bardziej uprościć, używając łańcucha tutaj, abycut -d. -3f- <<<"$record"
uzyskać lepszą wydajność. Mówimycut
dwie rzeczy: Po pierwsze-d
, powinien to być określony separator do identyfikowania pól (tak jak wsort
przypadku separatora.
). Drugiecut
polecenie-f
jest drukowane tylko wartości z określonych pól; lista pól jest podana jako zakres3-
wskazujący wartość z trzeciego pola i ze wszystkich następujących pól. Oznacza to, żecut
przeczyta i zignoruje wszystko aż do sekundy.
, którą znajdzie w rekordzie, a następnie wydrukuje resztę, czyli ścieżkę do pliku.Po wydrukowaniu najnowszej ścieżki do pliku nie trzeba kontynuować:
break
wychodzi z pętli, nie pozwalając jej przejść do drugiej ścieżki do pliku.Pozostaje tylko uruchomienie
tail
ścieżki pliku zwróconej przez ten potok. Być może zauważyłeś w moim przykładzie, że zrobiłem to, umieszczając potok w podpowłoce; to, czego być może nie zauważyłeś, to to, że umieściłem podpowłokę w podwójnych cudzysłowach. Jest to ważne, ponieważ w końcu nawet przy tych wszystkich wysiłkach, aby być bezpiecznym dla nazw plików, niecytowane rozszerzenie podpowłoki może nadal zepsuć. Bardziej szczegółowe wyjaśnienie jest dostępna, jeśli jesteś zainteresowany. Drugim ważnym, ale łatwo przeoczanym aspektem wywołaniatail
jest to, że podałem opcję--
przed rozwinięciem nazwy pliku. To pouczytail
że nie określono już żadnych opcji, a wszystko, co następuje, to nazwa pliku, dzięki czemu można bezpiecznie obsługiwać nazwy plików zaczynające się od-
.źródło
tail -f $(find . -type f -exec stat -f "%m {}" {} \;| sort -n | tail -n 1 | cut -d ' ' -f 2)
head
itail
nie akceptują przełączników, aby działały na danych rozdzielanych znakiem zerowym”. Mój zamiennikhead
:… | grep -zm <number> ""
.Jeśli martwisz się nazwami plików ze spacjami,
źródło
Możesz użyć:
$()
Konstrukt rozpoczyna sub-shell, który uruchamia poleceniels -1t
(z wyszczególnieniem wszystkich plików w porządku chronologicznym, po jednej w wierszu) i orurowanie że przezhead -1
uzyskać pierwszą linię (plik).Dane wyjściowe tego polecenia (najnowszego pliku) są następnie przekazywane do
tail
przetworzenia.Należy pamiętać, że grozi to uzyskaniem katalogu, jeśli jest to najnowszy utworzony wpis w katalogu. Użyłem tej sztuczki w aliasie, aby edytować najnowszy plik dziennika (z zestawu obrotowego) w katalogu, który zawierał tylko te pliki dziennika.
źródło
-1
nie jest konieczne,ls
robi to dla ciebie, gdy jest w rurze. Porównajls
ils|cat
na przykład.W systemach POSIX nie ma możliwości uzyskania pozycji katalogu „ostatnio utworzony”. Każda pozycja katalogu ma
atime
,mtime
ictime
, ale w przeciwieństwie do systemu Microsoft Windows,ctime
nie znaczy CreationTime, ale „czas ostatniej zmiany stanu”.Więc najlepsze, co możesz uzyskać, to „ogonić ostatnio zmodyfikowany plik”, co wyjaśniono w innych odpowiedziach. Wybrałbym to polecenie:
Zwróć uwagę na cytaty wokół
ls
polecenia. Dzięki temu fragment kodu działa z prawie wszystkimi nazwami plików.źródło
Chcę tylko zobaczyć zmianę rozmiaru pliku, którego można użyć zegarka.
źródło
W
zsh
:Zobacz: http://zsh.sourceforge.net/Doc/Release/Expansion.html#Glob-Qualifiers , tutaj
m
oznacza czas modyfikacjim[Mwhms][-|+]n
, a powyższyo
oznacza, że jest on sortowany w jeden sposób (O
sortuje w inny sposób). W.
jedynym środkiem zwykłe pliki. W nawiasach[1]
wybiera pierwszy element. Aby wybrać trzy użycie[1,3]
, aby uzyskać najstarsze użycie[-1]
.Jest ładny krótki i nie używa
ls
.źródło
Prawdopodobnie jest na to milion sposobów, ale chciałbym to zrobić w następujący sposób:
Bity między znakami odwrotnymi (znaki podobne do cudzysłowu) są interpretowane, a wynik wraca do końca.
źródło
Prosty:
działa dobrze dla mnie.
Problemem jest uzyskanie plików, które są generowane po uruchomieniu polecenia tail. Ale jeśli nie potrzebujesz tego (ponieważ wszystkie powyższe rozwiązania nie dbają o to), gwiazdka jest po prostu prostszym rozwiązaniem, IMO.
źródło
źródło
Ktoś to opublikował, a następnie z jakiegoś powodu usunął, ale to jedyny, który działa, więc ...
źródło
ls
nie jest najmądrzejszą rzeczą do zrobienia ...Wyjaśnienie:
źródło
źródło