TL; DR: najlepszym sposobem jest użycie -exec rmzamiast -delete.
find a \( -name b -prune \) -o -type f -exec rm {} +
Wyjaśnienie:
Dlaczego znaleźć narzekać podczas próby korzystania -deletez -prune?
Krótka odpowiedź: ponieważ -deleteimplikuje -depthi -depthczyni -prunenieskutecznym.
Zanim przejdziemy do długiej odpowiedzi, najpierw obserwuj zachowanie find zi bez -depth:
$ find foo/
foo/
foo/f1
foo/bar
foo/bar/b2
foo/bar/b1
foo/f2
Nie ma gwarancji na zamówienie w jednym katalogu. Istnieje jednak gwarancja, że katalog zostanie przetworzony przed zawartością. Uwaga foo/przed jakimkolwiek foo/*i foo/barprzed jakimkolwiek foo/bar/*.
Można to odwrócić za pomocą -depth.
$ find foo/ -depth
foo/f2
foo/bar/b2
foo/bar/b1
foo/bar
foo/f1
foo/
Zauważ, że teraz wszystkie foo/*pojawiają się wcześniej foo/. To samo z foo/bar.
Dłuższa odpowiedź:
-pruneuniemożliwia zejście find do katalogu. Innymi słowy, -prunepomija zawartość katalogu. W twoim przypadku -name b -pruneuniemożliwia znalezienie zejście do dowolnego katalogu o nazwie b.
-depthwyszukuje, aby przetworzyć zawartość katalogu przed samym katalogiem. Oznacza to, że do czasu, aż find przetworzy pozycję katalogu, bjej zawartość została już przetworzona. W związku z tym -prunejest nieskuteczny -depth.
-deleteoznacza -depth, że może najpierw usunąć pliki, a następnie pusty katalog. -deleteodmawia usunięcia niepustych katalogów. Myślę, że byłoby możliwe dodanie opcji wymuszenia -deleteusunięcia niepustych katalogów i / lub zapobieżenia -deletesugerowaniu -depth. Ale to inna historia.
Istnieje inny sposób na osiągnięcie tego, co chcesz:
find a -not -path "*/b*" -type f -delete
To może być łatwiejsze do zapamiętania.
To polecenie wciąż schodzi do katalogu bi przetwarza każdy pojedynczy plik tylko po to, -notaby je odrzucić. Może to być problem z wydajnością, jeśli katalog bjest ogromny.
-pathdziała inaczej niż -name. -namepasuje tylko do nazwy (pliku lub katalogu), podczas gdy -pathpasuje do całej ścieżki. Na przykład obserwuj ścieżkę /home/lesmana/foo/bar. -name -barbędzie pasować, ponieważ nazwa to bar. -path "*/foo*"będzie pasować, ponieważ ciąg /fooznajduje się na ścieżce. -pathma pewne zawiłości, które powinieneś zrozumieć przed użyciem. Przeczytaj stronę podręcznika, findaby uzyskać więcej informacji.
Uważaj, że nie jest to w 100% niezawodne. Istnieją szanse na „fałszywe alarmy”. Sposób, w jaki powyższe polecenie jest napisane, pomija każdy plik, który ma dowolny katalog nadrzędny, którego nazwa zaczyna się od b(dodatnia). Ale pominie także każdy plik, którego nazwa zaczyna się bniezależnie od pozycji w drzewie (fałszywie dodatni). Można to naprawić, pisząc lepsze wyrażenie niż "*/b*". Zostało to ćwiczeniem dla czytelnika.
Zakładam, że użyłeś ai bjako symbole zastępcze, a prawdziwe nazwiska są bardziej podobne do allosaurusi brachiosaurus. Jeśli wstawisz brachiosaurusw miejsce bwówczas ilość fałszywych alarmów zostanie drastycznie zmniejszona.
Przynajmniej fałszywe pozytywy będzie nie usunięte, więc będzie nie być tak tragiczne. Co więcej, możesz sprawdzić fałszywe alarmy, uruchamiając najpierw komendę bez -delete(ale pamiętaj, aby umieścić domyślną -depth) i sprawdź dane wyjściowe.
find a -not -path "*/b*" -type f -depth
apoza wyjątkiema/b?