Wbudowane test
i [
narzędzia mają testy -nt
(„nowsze niż”) i -ot
(„starsze niż”) w większości powłok, nawet gdy powłoka działa w „trybie POSIX” (dotyczy to również zewnętrznych narzędzi o tych samych nazwach w systemy, do których mam dostęp). Testy te służą do porównywania znaczników czasu modyfikacji dwóch plików. Ich udokumentowana semantyka różni się nieznacznie w zależności od implementacji (w odniesieniu do tego, co się stanie, jeśli jeden lub drugi plik nie istnieje), ale nie są one uwzględnione w specyfikacji POSIX. dla test
narzędzia .
Nie zostały przeniesione do
test
narzędzia, gdy polecenie warunkowe zostało usunięte z powłoki [KornShell], ponieważ nie zostały uwzględnione wtest
narzędziu wbudowanym w historyczne implementacjesh
narzędzia.
Zakładając, że chciałbym porównać znacznik czasu modyfikacji między plikami w /bin/sh
skrypcie powłoki, a następnie podjąć działania w zależności od tego, czy jeden plik jest nowszy od drugiego, jak w
if [ "$sigfile" -nt "$timestamp" ] ||
[ "$sigfile.tmp" -nt "$timestamp" ]
then
return
fi
... jakiego innego narzędzia mógłbym użyć oprócz make
(co sprawiłoby, że reszta skryptu byłaby co najmniej niewygodna)? A może powinienem po prostu założyć, że nikt nigdy nie uruchomi skryptu na „historycznej implementacji sh
” lub nie zrezygnuje z pisania dla określonej powłoki bash
?
źródło
-nt
funkcjitest
w sposób, który jest oczekiwany od ok. 1995. Powinieneś używaćfind
wyrażenia basd, nawetbash
jeśli lubisz prawidłowe zachowanie.Odpowiedzi:
POSIXLY:
Użycie bezwzględnej ścieżki do plików zapobiega fałszywie dodatniemu, gdy nazwa pliku zawiera tylko znaki nowej linii.
W przypadku użycia ścieżki względnej zmień
find
polecenie na:źródło
$f1
zawiera tylko nowe wiersze;)-exec echo x \;
podobny sposób?-printf
byłoby łatwo, gdyby to był standardfind
status wyjścia jest niezależny od tego, co poszczególne testyfind
powrotu - z wyjątkiem być może błędu w uruchomieniu tych testów.find
kończy 0, nawet jeśli nie znaleziono plików.[ / -nt /nofile ]
różni się w zależności od implementacji (ale nigdy nie generuje żadnego błędu).Może to być przypadek stosując jedną z najstarszych polecenia Unix
ls
.Wynik jest prawdziwy, jeśli a jest nowsze niż b.
źródło
-
(brak--
). Trzeba by-L
to było równoważne-nt
. Że nie działa, aby porównaćx
i$'x\nx'
na przykład.Zadałeś interesujące pytanie i zgłosiłeś roszczenie, które należy najpierw zweryfikować.
Sprawdziłem zachowanie:
z różnymi skorupkami. Oto wyniki:
bash Nie działa - nic nie drukuje.
bosh działa
myślnik nie działa - nic nie drukuje.
ksh88 Nie działa - nic nie drukuje.
działa ksh93
mksh Nie działa - nic nie drukuje.
posh print: posh: [: -nt: nieoczekiwany operator / operand
yash działa
zsh działa w nowszych wersjach , starsze wersje nic nie drukują
Tak więc cztery z dziewięciu powłok obsługują funkcję -nt i poprawnie ją implementują. Prawidłowo w tym przypadku oznacza: jest w stanie porównać znaczniki czasu na najnowszych platformach, które obsługują szczegółowość znaczników czasu w sekundach . Zauważ, że pliki, które wybrałem, różnią się zwykle tylko kilkoma mikrosekundami w swoich znacznikach czasu.
Ponieważ łatwiej jest znaleźć działającą
find
implementację, zalecam wymianęprzez
find
wyrażenie oparte.działa przynajmniej tak długo, jak długo
$file1
zawiera nie tylko nowe wiersze.jest nieco wolniejszy, ale działa poprawnie.
BTW: Jeśli chodzi o markę, nie mogę mówić o wszystkich implementacjach make, ale
SunPro Make
obsługuje porównanie czasu z ziarnistością nanosekundową od ok. 20 lat, podczas gdysmake
igmake
dodaje tę funkcję niedawno.źródło
find
implementacje, takie jak busybox lub heirloom-toolchest, będą miały takie same ograniczenia.-L
dla Thefind
wersja za równoważne-nt
. Byłoby to również nie na nazwy plików, które rozpoczynają się-
lub!
,(
...find
mająfind -f "$file"
to, ale nie jest przenośne.