W Bash chciałbym stworzyć funkcję, która zwraca nazwę najnowszego pliku, który pasuje do określonego wzorca. Na przykład mam katalog plików takich jak:
Directory/
a1.1_5_1
a1.2_1_4
b2.1_0
b2.2_3_4
b2.3_2_0
Chcę najnowszy plik zaczynający się od „b2”. Jak mam to zrobić w bash? Muszę to mieć w swoim ~/.bash_profile
skrypcie.
Odpowiedzi:
ls
Komenda ma parametr-t
sortowania przez czas. Następnie możesz pobrać pierwszy (najnowszy) zhead -1
.Ale uważaj: dlaczego nie powinieneś analizować wyjścia ls
Moja osobista opinia: parsowanie
ls
jest niebezpieczne tylko wtedy, gdy nazwy plików mogą zawierać zabawne znaki, takie jak spacje lub znaki nowej linii. Jeśli możesz zagwarantować, że nazwy plików nie będą zawierały zabawnych znaków, parsowaniels
jest całkiem bezpieczne.Jeśli tworzysz skrypt, który ma być uruchamiany przez wiele osób na wielu systemach w różnych sytuacjach, to bardzo polecam, aby go nie analizować
ls
.Oto jak to zrobić "dobrze": Jak mogę znaleźć najnowszy (najnowszy, najwcześniejszy, najstarszy) plik w katalogu?
źródło
ls
,printf "%s\n" b2* | head -1
zrobię to za Ciebie.b2.10_5_2
zabija to rozwiązanie.Połączenie
find
ils
działa dobrze w przypadkuRozwiązanie:
Rozbijmy to:
Dzięki temu
find
możemy dopasować wszystkie interesujące pliki, takie jak:następnie używając
-print0
możemy bezpiecznie przekazać wszystkie nazwy plików dols
tego:find
można tutaj dodać dodatkowe parametry wyszukiwania i wzorcels -t
posortuje pliki według czasu modyfikacji (od najnowszych) i wydrukuje je jeden w wierszu. Możesz użyć-c
do sortowania według czasu utworzenia. Uwaga : to zepsuje się w przypadku nazw plików zawierających znaki nowej linii.W końcu
head -1
dostajemy pierwszy plik na posortowanej liście.Uwaga:
xargs
użyj ograniczeń systemowych do rozmiaru listy argumentów. Jeśli ten rozmiar przekroczy,xargs
zadzwonils
wiele razy. Spowoduje to przerwanie sortowania i prawdopodobnie również ostateczny wynik. Biegaćaby sprawdzić limity w Twoim systemie.
Uwaga 2: użyj,
find . -maxdepth 1 -name "my-pattern" -print0
jeśli nie chcesz przeszukiwać plików przez podfoldery.Uwaga 3: Jak wskazał @starfry -
-r
argument zaxargs
uniemożliwia wywołanie programuls -1 -t
, jeśli żaden plik nie został dopasowany przez rozszerzeniefind
. Dziękuję za sugestię.źródło
find . -name "my-pattern" ... -print0
daje mifind: paths must precede expression: `...'
...
oznacza „więcej parametrów”. Po prostu go pomiń, jeśli go nie potrzebujesz.-r
do wiersza poleceń xargs, który mówi xargs, aby nie uruchamiał swojego wiersza poleceń, jeśli nic nie otrzyma ze swojego standardowego wejścia.-r
do odpowiedzi.Oto możliwa implementacja wymaganej funkcji Bash:
Używa tylko wbudowanych Bash i powinien obsługiwać pliki, których nazwy zawierają znaki nowej linii lub inne nietypowe znaki.
źródło
nullglob_shopt=$(shopt -p nullglob)
a później$nullglob
przywrócićnullglob
to, jak było wcześniej.$()
lub znaków odwrotnych), ponieważ jest powolny, szczególnie pod Cygwin, nawet jeśli polecenie używa tylko poleceń wbudowanych. Ponadto kontekst podpowłoki, w którym polecenia są uruchamiane, może czasami powodować, że zachowują się one w nieoczekiwany sposób. Staram się również unikać przechowywania poleceń w zmiennych (takich jaknullglob_shopt
), ponieważ mogą się zdarzyć bardzo złe rzeczy, jeśli źle otrzymasz wartość zmiennej.cat
!”. Nawet jeśli wymaga to więcej pracy, ma tę zaletę, że pokazuje ludziom koncepcje. Zdobądź +1!Nietypowe nazwy plików (na przykład plik zawierający prawidłowy
\n
znak mogą siać spustoszenie przy tego rodzaju analizowaniu. Oto sposób, aby to zrobić w Perlu:To jest zastosowana tam transformacja Schwartza .
źródło
Możesz użyć
stat
z plikiem glob i dekoracją-sortowaniem-undecorate z czasem pliku dodanym z przodu:źródło
stat
, jeśli dobrze pamiętam jego opcje. Aby uzyskać podobne wyniki na innych platformach, możesz użyćstat -c $'%Y\t%n' b2* | sort -rn | head -n1 | cut -f2-
Inkantacja funkcji czarnej magii dla tych, którzy chcą
find ... xargs ... head ...
powyższego rozwiązania, ale w łatwej w użyciu formie funkcji, więc nie musisz myśleć:Wydruki:
Który jest:
Nazwa pliku z najstarszym zmodyfikowanym znacznikiem czasu pliku w podanym katalogu pasującym do podanego wzorca.
źródło
Użyj polecenia znajdź.
Zakładając, że używasz Bash 4.2+, użyj
-printf '%T+ %p\n'
jako wartości znacznika czasu pliku.Przykład:
Aby uzyskać bardziej przydatny skrypt, zobacz najnowszy skrypt znajdujący się tutaj: https://github.com/l3x/helpers
źródło
Jest o wiele skuteczniejszy sposób osiągnięcia tego. Rozważ następujące polecenie:
To polecenie znajduje najnowszy plik utworzony dokładnie minutę temu przy wyszukiwaniu symboli wieloznacznych na „b2 *”. Jeśli chcesz pliki z ostatnich dwóch dni, lepiej będzie, używając poniższego polecenia:
„.” reprezentuje bieżący katalog. Mam nadzieję że to pomoże.
źródło