Ostatnio stanąłem przed zadaniem usunięcia wszystkich plików / folderów z katalogu oprócz tych pasujących do określonego wzorca. Przygotowałem więc jednoliniowe polecenie unixowe do wykonania pracy. Czy to musi być tylko jedna linia? Chyba nie, ale w ten sposób jest zdecydowanie chłodniej!
Chociaż problem jest dość prosty, byłem trochę zaskoczony, jak skomplikowane stało się moje rozwiązanie. Oto polecenie, którego użyłem; UWAGA: jest to złe rozwiązanie, ponieważ nie obsługuje nazw plików zawierających znaki przesunięcia wiersza (co nie miało znaczenia w mojej sytuacji).
ls | grep -v PATTERN | xargs -n1 -IREPLACE rm -rf REPLACE
Nie użyłem polecenia „znajdź”, ponieważ nie chcę się ponownie zapisywać w folderach pasujących do WZORCA. Rozważmy na przykład następującą strukturę plików:
file_foo.txt
first_dir
|
+--> contents
+--> ...
foo_dir
|
+--> anotherfile.txt
+--> morefiles.log
foo_file.txt
somefile.txt
Użycie wzorca „foo” musi usuwać tylko „first_dir” (i oczywiście jego zawartość) oraz „somefile.txt” ( nie „anotherfile.txt” ani „morefiles.log”).
Pytanie, czy są lepsze (bardziej eleganckie i poprawne) sposoby na osiągnięcie tego?
EDYCJA:
Ostatnio zwrócono mi uwagę, że lepszym rozwiązaniem może być „znajdź” :
find * -maxdepth 0 ! -name PATTERN -print0 | xargs -0n1 rm -rf
To rozwiązanie poprawnie obsługuje ścieżki zawierające znaki nowego wiersza.
źródło
Odpowiedzi:
Poniższe przykłady mają
echo
prefiks, dzięki czemu można przetestować wzorce przed ich użyciem. Usuń,echo
aby aktywowaćrm -rf
. Zastąprm -ri
prośbę o potwierdzenie.ksh ma rozszerzenie dopasowania ujemnego do globowania:
Ta sama składnia jest dostępna w bash, jeśli ustawisz
extglob
opcję:zsh ma do tego swoją własną składnię:
Może także używać składni w stylu ksh :
źródło
shopt -s extglob
do mojego pliku .bashrc, więc teraz jest to jednowierszowy). Doskonały! Obiecuję głosowanie, gdy tylko moja reputacja na to pozwoli.Oto inne
find
rozwiązanie. Nie jestem pewien, czy ma to jakąś rzeczywistą przewagę nad twoją, ale nie potrzebujexargs
i pozwala na rzadką możliwość, że * rozszerza się na zbyt wiele nazw.Dodałem również
-type f
, aby nie próbowało usuwać katalogów.Ostrzeżenie:
-delete
jest potężny. Dałem jednemu z moich plików testowych 0 uprawnień, a powyższe polecenie usunęło je bez wahania.źródło
-delete
się-print
, aby zobaczyć, czy to ze znalezieniem plików chciałeś. Jeśli wszystko jest w porządku, użyj historii poleceń (np. Naciśnij przycisk w górę), aby wrócić do poprzedniego polecenia i upewnić się, że pracujesz z tymi samymi filtrami wyszukiwania.find -delete
nie usunie niepustych katalogów. Zauważ też, żefind -maxdepth 1
pasuje do „.” (bieżący katalog), co jest naprawdę złe. Chociaż podoba mi się twój pomysł wyeliminowaniaxargs
, można użyćfind -exec
alternatywnie.find * -maxdepth 0 ! -name PATTERN -exec rm -rf '{}' \;
Zamiast tego możesz użyć tego przykładu skryptu zbrojenia http://askcodegeneration.com/keep-subversion/, który jest znacznie bardziej zrozumiały i który może zarządzać interakcją użytkownika, taką jak wybór folderu i potwierdzenie:
źródło