Najprawdopodobniej usunięcie bieżącego katalogu roboczego nie byłoby dobrym pomysłem.
Alexej Magura,
Uzgodnione - podoba mi się zachowanie domyślne, ale nie jest zgodne z np find . -print.
mbroshi,
@AlexejMagura chociaż sympatyzuję, nie rozumiem, dlaczego usunięcie bieżącego katalogu powinno być inne niż usunięcie otwartego pliku. Obiekt pozostanie przy życiu, dopóki nie będzie odniesienia do niego, a następnie zostaną usunięte śmieci. Możesz zrobić cd ..; rm -r dirz inną powłoką z dość wyraźną semantyką ...
Rmano,
@Rmano to prawda: to po prostu coś, czego nie zrobiłbym w zasadzie: po prostu przejdź do katalogu, a następnie usuń bieżący katalog. Nie jestem do końca pewien, dlaczego to taka wielka sprawa - chociaż miałem pewne nieszczęścia, że bieżący katalog już nie istnieje, takie jak ścieżki względne, które już nie działają, ale zawsze możesz wydostać się, używając ścieżki bezwzględnej - ale jakaś część mnie mówi, że ogólnie nie jest to dobry pomysł.
Alexej Magura,
Odpowiedzi:
29
Członkowie findutilsświadomi tego , jest to zgodne z * BSD:
Jednym z powodów, dla których pomijamy usunięcie „”. dotyczy zgodności z * BSD, z którego pochodzi ta akcja.
NEWS w kodzie źródłowym Findutils pokazuje, że zdecydowali się zachować zachowanie:
#20802: If -delete fails, find's exit status will now be non-zero. However, find still skips trying to delete ".".
[AKTUALIZACJA]
Ponieważ pytanie to stało się jednym z gorących tematów, zagłębiam się w kod źródłowy FreeBSD i podam bardziej przekonujący powód.
Tak jak powinno: POSIX jest królem, a usunięcie bieżącego katalogu może spowodować bardzo duże problemy w zależności od aplikacji nadrzędnej, a co nie. Jak gdyby bieżący katalog był /var/logi uruchomiłeś go jako root, myśląc, że usunie wszystkie podkatalogi, a także katalog bieżący?
Alexej Magura,
1
To dobra teoria, ale manstrona z findhasłem mówi: „Jeśli usunięcie się nie powiedzie, zostanie wyświetlony komunikat o błędzie”. Dlaczego nie jest drukowany błąd?
mbroshi,
1
@AlexejMagura Usuwanie bieżący katalog działa dobrze w ogóle: mkdir foo && cd foo && rmdir $(pwd). Usuwanie .(lub ..), które nie działa.
Znaczenie usuwania ścieżki / kropki jest niejasne, ponieważ nazwa pliku (katalogu) w katalogu nadrzędnym, który ma zostać usunięty, nie jest jasna, szczególnie w obecności wielu łączy do katalogu.
Chociaż 林果 皞 i Thomas już udzielili na to dobrych odpowiedzi, wydaje mi się, że ich odpowiedzi zapomniały wyjaśnić, dlaczego to zachowanie zostało wdrożone w pierwszej kolejności.
W twoim find . -deleteprzykładzie usunięcie bieżącego katalogu brzmi dość logicznie i rozsądnie. Ale zastanów się:
$ find . -name marti\*
./martin
./martin.jpg
[..]
Czy usunięcie .nadal wydaje ci się logiczne i rozsądne?
Usunięcie niepustego katalogu jest błędem - więc jest mało prawdopodobne, że stracisz przy tym dane find(chociaż możesz to zrobić rm -r) - ale w twojej powłoce będzie ustawiony bieżący katalog roboczy na katalog, który już nie istnieje, co może powodować mylące i zaskakujące zachowanie:
$ pwd
/home/martin/test
$ rm -r ../test
$ touch foo
touch: cannot touch 'foo': No such file or directory
Nie usuwając bieżący katalog jest po prostu dobry design interfejsu i jest zgodny z zasadą najmniejszego zaskoczenia.
find . -print
.cd ..; rm -r dir
z inną powłoką z dość wyraźną semantyką ...Odpowiedzi:
Członkowie
findutils
świadomi tego , jest to zgodne z * BSD:NEWS w kodzie źródłowym Findutils pokazuje, że zdecydowali się zachować zachowanie:
[AKTUALIZACJA]
Ponieważ pytanie to stało się jednym z gorących tematów, zagłębiam się w kod źródłowy FreeBSD i podam bardziej przekonujący powód.
Zobaczmy kod źródłowy narzędzia FreeBSD :
Jak widać, jeśli nie odfiltruje kropki i kropki, osiągnie
rmdir()
funkcję C zdefiniowaną przez POSIXunistd.h
.Wykonaj prosty test, rmdir z argumentem kropka / kropka-kropka zwróci -1:
Zobaczmy, jak POSIX opisuje rmdir :
Nie podano powodu
shall fail
.Znalazłem
rename
wyjaśnienie kilku powodów :Cykliczne ścieżki systemu plików ?
Spoglądam na język programowania C (wydanie drugie) i szukam tematu katalogu, co zaskakujące, stwierdziłem, że kod jest podobny :
I komentarz!
„pętla na zawsze” , to tak samo, jak
rename
opisujemy to jako „cykliczne ścieżki systemu plików” powyżej.Lekko modyfikuję kod i uruchamiam go w Kali Linux na podstawie tej odpowiedzi :
Zobaczmy:
Działa poprawnie, co teraz, jeśli skomentuję
continue
instrukcję:Jak widać, muszę użyć Ctrl+, Caby zabić ten program nieskończonej pętli.
Katalog „..” czyta swój pierwszy wpis „..” i zapętla na zawsze.
Wniosek:
GNU
findutils
próbuje kompatybilić zfind
narzędziem w * BSD .find
narzędzie w * BSD wewnętrznie korzystarmdir
z funkcji C zgodnej z POSIX, której kropka / kropka nie jest dozwolona.Przyczyną
rmdir
niedozwolenia kropka / kropka-kropka jest zapobieganie cyklicznym ścieżkom systemu plików.Język programowania C napisany przez K&R pokazuje przykład, jak kropka / kropka-kropka doprowadzi do programu na zawsze.
źródło
Ponieważ twoje
find
polecenie zwraca.
jako wynik. Ze strony informacyjnejrm
:Wygląda na to, że
find
w tym przypadku po prostu trzyma się reguł POSIX.źródło
/var/log
i uruchomiłeś go jako root, myśląc, że usunie wszystkie podkatalogi, a także katalog bieżący?man
strona zfind
hasłem mówi: „Jeśli usunięcie się nie powiedzie, zostanie wyświetlony komunikat o błędzie”. Dlaczego nie jest drukowany błąd?mkdir foo && cd foo && rmdir $(pwd)
. Usuwanie.
(lub..
), które nie działa.Wywołanie systemowe rmdir kończy się niepowodzeniem z EINVAL, jeśli ostatnim składnikiem ścieżki argumentu jest
"."
. Jest to udokumentowane na stronie http://pubs.opengroup.org/onlinepubs/009695399/functions/rmdir.html, a uzasadnienie takiego zachowania jest następujące:źródło
Wywołanie
rmdir(".")
jako wywołanie systemowe nie działało, kiedy próbowałem, więc żadne narzędzie wyższego poziomu nie może odnieść sukcesu.Musisz usunąć katalog, używając jego prawdziwej nazwy, a nie
.
aliasu.źródło
Chociaż 林果 皞 i Thomas już udzielili na to dobrych odpowiedzi, wydaje mi się, że ich odpowiedzi zapomniały wyjaśnić, dlaczego to zachowanie zostało wdrożone w pierwszej kolejności.
W twoim
find . -delete
przykładzie usunięcie bieżącego katalogu brzmi dość logicznie i rozsądnie. Ale zastanów się:Czy usunięcie
.
nadal wydaje ci się logiczne i rozsądne?Usunięcie niepustego katalogu jest błędem - więc jest mało prawdopodobne, że stracisz przy tym dane
find
(chociaż możesz to zrobićrm -r
) - ale w twojej powłoce będzie ustawiony bieżący katalog roboczy na katalog, który już nie istnieje, co może powodować mylące i zaskakujące zachowanie:Nie usuwając bieżący katalog jest po prostu dobry design interfejsu i jest zgodny z zasadą najmniejszego zaskoczenia.
źródło