Usuń pliki i katalogi według ich nazw. Brak takiego pliku lub katalogu

32

Muszę usunąć wszystkie skompilowane dane:

  • nazwane katalogi build,
  • nazwane katalogi obj,
  • * Pliki .so.

Napisałem polecenie

find \( -name build -o -name obj -o -name *.so \) -exec rm -rf {} \;

które rekursywnie przegląda wszystkie katalogi i usuwa wszystko, czego potrzebuję.

Dlaczego mam takie wyjście na końcu? Może powinienem napisać inne polecenie.

find: `./3/obj': No such file or directory
find: `./3/build': No such file or directory
find: `./1/obj': No such file or directory
find: `./1/build': No such file or directory
find: `./2/obj': No such file or directory
find: `./2/build': No such file or directory
Maksim Dmitriew
źródło
w jakim systemie jesteś? powinieneś zawsze używać findtego w find /search_directory optionstaki sposób, że pominięcie katalogu wyszukiwania nie jest dobrym pomysłem
Kiwy
Zautomatyzowane usuwanie tego typu jest złym pomysłem. Możesz mieć skrypt, który da ci kandydatów, na które powinieneś spojrzeć, aby upewnić się, że nie usuwasz niczego ważnego lub koniecznego dla systemu. Nie masz jednoznacznego określenia, gdzie to działa. Jeśli robisz to tylko w przestrzeni użytkownika, przypuszczam, że nie może to wyrządzić wiele szkody, ale powinieneś upewnić się, że nie robisz tego przypadkowo w obszarze systemowym. Zdecydowanie chcesz uruchomić taki skrypt jako użytkownik.
Faheem Mitha
@ Kiwy, @ FaheemMitha, polecenie będzie użyte tylko w katalogu projektu; nie wyrządzi tam żadnej szkody.
Maksim Dmitriev
Powiązane: stackoverflow.com/questions/22462124/…
Ciro Santilli 29 改造 中心 法轮功 六四 事件

Odpowiedzi:

54

Skorzystaj -prunez katalogów, które i tak chcesz usunąć, aby findnie zawracać sobie głowy próbą znalezienia w nich plików:

find . \( -name build -o -name obj -o -name '*.so' \) -prune -exec rm -rf {} +

Należy również zauważyć, że *.sonależy go zacytować, ponieważ w przeciwnym razie powłoka może go rozwinąć do listy .soplików w bieżącym katalogu.

Odpowiednikiem twojego -regextypu GNU byłoby:

find . \( -name build -o -name obj -o -name '*?.so' \) -prune -exec rm -rf {} +

Zauważ, że jeśli zamierzasz użyć składni specyficznej dla GNU, równie dobrze możesz użyć -deletezamiast -exec rm -rf {} +. Za pomocą -deleteGNU findwłącza się -depthautomatycznie. Nie uruchamia zewnętrznych poleceń, dzięki czemu jest bardziej wydajny, a także bezpieczniejszy, ponieważ usuwa warunki wyścigu, w których ktoś może sprawić, że usuniesz niewłaściwe pliki, zmieniając katalog na dowiązanie symboliczne między czasem findznajduje plik i rmusuwa go (zobacz info -f find -n 'Security Considerations for find'szczegóły).

find . -regextype posix-egrep -regex '.*/((obj|build)(/.*)?|.+\.so)' -delete
Stéphane Chazelas
źródło
-deletelepiej radzi sobie również z takimi przestrzeniami
Izkata,
@Izkata, nie lepiej niż -exec rm -rf {} +które nie mają z nimi problemu.
Stéphane Chazelas
@StephaneChazelas - jestem zdezorientowany {}- czy należy je cytować, czy nie? Wydaje się, że działa bez cudzysłowów, ale na przykład używa GNU Findutils Manual'{}' . Czy mógłbyś wyjaśnić?
grebneke
1
@grebneke, myślę, że jest gdzieś post, w którym cytaty mogą być potrzebne w bardzo starych wersjach csh, ale nigdy nie mogłem zweryfikować tego twierdzenia. Nie są potrzebne w żadnej nowoczesnej powłoce, którą znam. Zdecydowanie nie są wymagane przez POSIX. Te przykłady POSIX z nich nie korzysta.
Stéphane Chazelas
3
I -deletenie można go używać z katalogami.
St0rM
8

Chyba dlatego, że findnajpierw usuwa drzewo katalogów i próbuje sprawdzić zawartość katalogu, co oczywiście nie jest najlepszą możliwą kolejnością. Możesz wymusić findnajpierw sprawdzenie zawartości:

find . -depth ...

Należy rozważyć użycie -deleteplików i -exec rmdirkatalogów.

Hauke ​​Laging
źródło
0

Moje rozwiązanie

find . -regextype posix-egrep -regex ".*/(obj|build|.+\.so)" -prune -exec rm -rf {} +

+ vs \; w poleceniu -exec

Maksim Dmitriew
źródło
To nie zawsze zadziała, tylko jeśli w usuniętym katalogu nie zachodzi granica między wykonaniami.
Gilles „SO- przestań być zły”
@Gilles, co oznacza „granica między egzekucjami”?
Maksim Dmitriev
1
-exec … {} +wykonuje polecenie dla wielu plików jednocześnie, tyle ile zmieści się w linii poleceń. Jeśli plików jest zbyt wiele (a dokładniej, jeśli całkowita długość ścieżek jest zbyt długa), findwykona wiele instancji rm, a tym samym może skończyć się usunięciem katalogu, który przemierza. Jest to po prostu mniej prawdopodobne +niż z ;, ale +nie rozwiązuje problemu.
Gilles „SO- przestań być zły”