Jak usunąć wszystkie podkatalogi z katalogu?

51

To pytanie jest jakby fazą II do pierwszego pytania, które tu zamieściłem

Mam katalog, który zawiera kilka podkatalogów, plików .zip i innych plików losowych nie zawartych w podkatalogu.

Chciałbym, aby skrypt wiersza poleceń usunął wszystkie podkatalogi z katalogu nadrzędnego, ale zachował wszystkie pliki zip i luźne pliki, które nie należą do żadnych podkatalogów. Wszystkie podkatalogi mają treść, więc uważam, że musiałbym wymusić ich usunięcie poleceniem -f.

Zasadniczo polecenie, które przegląda katalog nadrzędny (lub bieżący), usuwa z niego wszystkie foldery, ale zachowuje całą pozostałą zawartość i pliki, które nie są folderem ani nie są zawarte w folderze.

Rozumiem, że usuwanie elementów z wiersza polecenia wymaga szczególnej ostrożności, ale podjąłem już wszelkie niezbędne środki ostrożności, aby wykonać kopię zapasową zdalnie.

Evster
źródło

Odpowiedzi:

61

W BASH możesz użyć końcowego ukośnika ( myślę, że powinien działać w dowolnej powłoce POSIX):

rm -R -- */

Zauważ, że --oddziela opcje od argumentów i pozwala usunąć wpisy zaczynające się od myślnika - w przeciwnym razie po rozwinięciu przez powłokę nazwa pozycji byłaby interpretowana jako opcja przez rm(to samo dotyczy wielu innych narzędzi wiersza poleceń).

Dodaj -fopcję, jeśli nie chcesz otrzymywać monitu o potwierdzenie podczas usuwania plików, których nie można zapisać.

Zauważ, że domyślnie ukryte katalogi (te, których nazwa zaczyna się na .) zostaną pozostawione same sobie.

Ważne zastrzeżenie: rozszerzenie */obejmuje również dowiązania symboliczne, które ostatecznie rozstrzygają się w plikach katalogu typu . W zależności od rmimplementacji rm -R -- thelink/albo po prostu usunie dowiązanie symboliczne, albo (w większości z nich) rekurencyjnie usunie zawartość połączonego katalogu, ale nie sam katalog ani dowiązanie symboliczne.

Jeśli jest używany zsh, lepszym rozwiązaniem byłoby użycie kwalifikatora globalnego do wybrania tylko plików katalogu typu:

rm -R -- *(/) # or *(D/) to include hidden ones

lub:

rm -R -- *(-/)

aby dołączyć dowiązania symboliczne do katalogów (ale ponieważ tym razem rozszerzenie nie ma końcowych znaków /s, to tylko dowiązanie symboliczne jest usuwane ze wszystkimi rmimplementacjami).

Z bashAT & T ksh, yashczy zshmożna zrobić:

set -- */
rm -R -- "${@%/}"

rozebrać końcowe /.

Peter
źródło
Piękny! To działa idealnie. Nie zdawałem sobie sprawy, że to takie łatwe. Czy miałbyś coś przeciwko opracowaniu opcji -r vs. -R i tego, co robią te polecenia? Wielkie dzięki.
Evster,
-r, -R, --recursiveSą synonimami czyli „usunąć katalogi i ich zawartość rekursywnie”.
Peter
czy możesz wyjaśnić, co - i * / zrobić?
amfibia
6
Możesz także powiedzieć rm -R ./*/- Pozwala to również uniknąć problemów z nazwami łączników.
l0b0
1
Uważaj tylko, aby nie zmienić kolejności * i /. rm -R - / * robi coś zupełnie innego, co może się nie zdarzyć: |
ChrisOdney
13

Oprócz metody wieloznacznej możesz także użyć find(przynajmniej GNU find), aby to zrobić:

find -mindepth 1 -maxdepth 1 -type d -print0 | xargs -0 rm -R

Podobnie jak w przypadku innych findwierszy, możesz uruchomić pierwszą część ( find -mindepth 1 -maxdepth 1 -type d), aby wyświetlić listę katalogów, które zostaną usunięte.

Bezpieczniejszą opcją jest zrobienie czegoś takiego:

find -mindepth 1 -maxdepth 1 -type d -print0 | xargs -0 mv -i -t ../to-rm
# or
mv -i -t ../to-rm */
# or
mv -i */ ../to-rm

każda z nich przeniesie wszystkie rzeczy ../to-rmzamiast je usuwać. Możesz sprawdzić, czy zrobiłeś to, co chciałeś, to rm -Rften katalog w wolnym czasie.

derobert
źródło
+1 za „Kosz CLI” to-rmi findładnie obsługuje katalogi zaczynające się od kropki (oprócz wszelkich innych kłopotliwych ucieczek). :)
Peter
Dzięki za wskazówkę. Podoba mi się pomysł przejścia do osobnego katalogu przed usunięciem. Pracuję za pośrednictwem terminala w systemie Mac OS X i uważam, że musiałbym zainstalować jakiś pakiet GNU, aby móc korzystać z poleceń -mindepth i -maxdepth, prawda?
Evster,
@Evster nie jest pewny, czy Mac OS X find je obsługuje. Domyślam się, że fink (czy to wciąż jest w pobliżu?) Może zainstalować znalezisko, które ma. Lub możesz je pominąć, a następnie przefiltrować listę utworzonych plików za pomocą grep. Zdecydowanie skorzystaj z opcji mv, istead of rm.
derobert
4

Możesz chcieć utworzyć skrypt dla niektórych z tych sugestii, a zwłaszcza rm -R -- */przechowywać go w folderze / usr / local / bin; lub utwórz plik alias~ / .bashrc. Ponieważ tak łatwo jest źle wpisać polecenie i zepsuć system - nawet pojedyncza litera i / lub kolejność liter mogą mieć katastrofalne konsekwencje - posłużyłoby to jako bardziej niezawodne rozwiązanie niż konieczność wpisywania różnych opcji i argumentów za każdym razem, gdy chcesz wykonać to zadanie.

Możesz także dołączyć do skryptu / polecenia opcję -i or --interactive=oncelub, -I or --interactive=alwaysktóra będzie służyć jako kolejne narzędzie, aby uniknąć niezamierzonego usunięcia.

Co więcej, coś takiego jak sugerowany derobert byłoby najlepsze; po prostu skopiuj / wklej skrypt do pliku / edytora terminali i dostosuj go do swoich konkretnych potrzeb, a pliki / katalogi zostaną przeniesione do jednego katalogu (którego zawartość możesz sprawdzić / zweryfikować), który możesz po prostu usunąć wydanie rm -rfpolecenia.

Inną opcją jest użycie aplikacji GUI, takiej jak menedżer plików, i po prostu wybierz wszystkie odpowiednie pliki / foldery, które chcesz usunąć. Sprawdź strony podręcznika dystrybucji, jeśli nie masz uprawnień.

Wreszcie, jeśli foldery są puste - w zasadzie proste nazwy plików - możesz użyć rmdirpolecenia, aby je usunąć. Nie działa na wszystko, co możesz chcieć usunąć, ale przyda się, gdy będziesz chciał wykonać „sprzątanie domu”. ** Możesz wypróbować -p --ignore-fail-on-non-emptyopcję, która pozwoli ci usunąć niektóre podkatalogi oraz ich puste „rodzice” - katalogi, w których się znajdują.

ILMostro_7
źródło
To naprawdę dobry pomysł na stworzenie osobnego skryptu, który mogę wywołać dla tego polecenia. Czy możesz wyjaśnić, co dokładnie robią opcje -i i -I? Dzięki!
Evster
-I opcja wyświetli monit raz po naciśnięciu „Enter”, aby potwierdzić, że chcesz to usunąć (gdy zaznaczono więcej niż 3 pliki / foldery); podczas gdy opcja -i wyświetli monit dla każdego pliku, na który możesz po prostu potwierdzić, naciskając „y” i „Enter” - wszystko oprócz odpowiedzi twierdzącej spowoduje pominięcie tego konkretnego pliku podczas procesu usuwania.
ILMostro_7
1

Najpierw musisz wyświetlić listę katalogów, a następnie usunąć je, nie przeszkadzając normalnym plikom, ls -d * /, wyświetla tylko podkatalogi, a potokowanie go za pomocą rm usuwa katalogi i zawartość, utrzymując luźne pliki nietknięte.

To polecenie powinno wykonać zadanie,

ls -d  */ | xargs rm -rf
Ankit Marothi
źródło
1
Jaka byłaby korzyść rm -rf -- */? printf '%s\0' */ | xargs -r0 rm -rf --pomógłby (w powłokach, w których printfjest wbudowany i nie ls) obejść zbyt duże błędy na liście argumentów , ale ls -d */ | xargs rm -rfnie dodaje niczego AFAICT oprócz dodatkowych problemów.
Stéphane Chazelas,
1
@AnthonyGeoghegan, tak, na przykład, jeśli istnieje katalog o nazwie " .."(spacja ..), to usunie zawartość katalogu nadrzędnego z niektórymi lsimplementacjami. I to nie tylko spacje, ale także inne puste znaki, nowa linia, pojedynczy cudzysłów, podwójny cudzysłów, odwrotny ukośnik i nazwy plików zaczynające się od -.
Stéphane Chazelas
2
@Ankit, możesz zacząć od mywiki.wooledge.org/ParsingLs
Stéphane Chazelas
1
Kiedy w pełni zrozumiesz sugestię @ StéphaneChazelas, printfaby użyć do wygenerowania listy, w której każda nazwa jest zakończona znakiem null, aby można ją było przetworzyć za xargspomocą -0opcji, radzę zmodyfikować odpowiedź, aby zaktualizować ją z jego odmianą. Byłbym całkiem pewny, że byłby szczęśliwy, gdybyś użył swojego fragmentu kodu, jeśli go rozumiesz i nauczyłeś się, jak chroni on przed niepożądanym zachowaniem spowodowanym przez niektóre nazwy plików, które potencjalnie mogą istnieć.
Anthony G - Sprawiedliwość dla Moniki
1
Korzystanie xargsma jedną zaletę w stosunku do zaakceptowanej odpowiedzi (działa, gdy w bieżącym katalogu jest bardzo duża liczba plików / katalogów), więc istnieje możliwość edytowania tego w użyteczną odpowiedź. Osobiście uważam, że odpowiadanie na pytania dotyczące wymiany stosów jest dobrym doświadczeniem w nauce - szczególnie gdy otrzymuję przydatne informacje zwrotne od innych użytkowników.
Anthony G - Sprawiedliwość dla Moniki
-1

rm -rf <directory name>. To działa. Już samo wpisanie rm <directory name>prowadzi do liczby pytań podrzędnych, w których każdy z podkatalogów musi zostać usunięty ręcznie. Ale, rm -rfpomaga w usuwaniu cały katalog wraz z jego sub katalogów naraz.

Riya Melvin
źródło
5
OP poprosił o zachowanie zawartości bieżącego katalogu.
Stephen Rauch