Usuwanie wszystkich plików w folderze oprócz plików X, Y i Z

17

Mam wiele plików i folderów w określonym folderze i chcę je wszystkie usunąć; chciałem jednak zachować pliki X, Y i Z.

Czy mogę zrobić coś takiego: rm * | but NOT grep | X or Y or Z

Amit
źródło
Zakładam, że mogę użyć jakiegoś wyrażenia regularnego, które to zrobi?
Amit

Odpowiedzi:

16

Zamiast używać rm, może być łatwiej użyć find . Takie polecenie usunie wszystko oprócz pliku o nazwie dokładnie „plik”

find . \! -name 'file' -delete

Wiele wersji powinno być w stanie obsługiwać globowanie i dopasowanie wyrażeń regularnych.

Możesz także przesłać dane wyjściowe find do rm

find . \! -name '*pattern*' -print0 | xargs --null rm 
Zoredache
źródło
3
Pozwala to zobaczyć dokładnie, jakie pliki zostaną usunięte poprzez usunięcie -deleteoraz jakie pliki zostaną zapisane poprzez usunięcie -deletei \!.
Shawn J. Goff,
1
ostrożny, findjest rekurencyjny! więc wszystkie podkatalogi plików, które nie pasują do „ wzorca ”, również zostaną usunięte
Alexandre Holden Daly
Sposób przez xargs wymaga -depth, aby zapobiec próbie usunięcia katalogów przed zawartymi w nich plikami. Myślę jednak, że rm również nie usunie katalogów.
użytkownik nieznany
9

Używanie zsh, z setopt EXTENDED_GLOB, używanie ~operatora ( oprócz )

rm -- *~(x|y|z)

lub ^operator (negacja):

rm -- ^(x|y|z)

Ale prawdopodobnie powinieneś zamiast tego przenieść pliki w inne miejsce, a następnie usunąć wszystko. Jest o wiele bezpieczniejszy pod względem poślizgnięć palców, takich jak zbyt wczesne trafienie.

wnoise
źródło
5

Późniejsze wersje bash mają extglobopcję powłoki, która daje ci składnię do robienia tego, co chcesz (sprawdź swoją stronę podręcznika w „Pathname Expansion”, aby zobaczyć, czy ma ją zainstalowana wersja):

$ shopt -s extglob  # turn on extended globbing
$ rm !(X|Y|Z)

Aby przetestować, proponuję najpierw wymienić rmze echoaby sprawdzić, czy lista plików, które mają zostać usunięte, co można się spodziewać.

camh
źródło
5
ls -1 | grep -v "^[XYZ]$" # | xargs rm -r

Uwaga: Uruchom polecenie i jeśli pliki do usunięcia są odpowiednie, uruchom je ponownie i usuń znak krzyżyka „#”.

Jeśli nazwy plików są bardziej skomplikowane, zrób to

ls -1 | egrep -v "^file1$|^filename2$|^f1le$" # | xargs rm -r

Ponownie, spójrz najpierw na wyniki, a następnie usuń znak skrótu.

Ta wersja - jak sugerowano w komentarzach - zapisuje niektóre postacie i wygląda nieco jaśniej.

ls -1 | egrep -v "^(file1|filename2|f1le)$" # | xargs rm -r
ddeimeke
źródło
Sugerowaną edycją ddeimeke jest zmiana egrepargumentu na"^(file1|filename2|f1le)$"
Michael Mrozek
Jeśli masz trzy pliki a, ba a bpierwszy program usunie - jeśli umieścisz ab do części grep: "^[ab]$" aa bjednak nie a b, po prostu w przeciwieństwie do swoich zamiarów. Drugie polecenie zrobi to samo. I trzeci też. Nie należy używać „ls” w skryptach, z bardzo, bardzo rzadkimi wyjątkami. Po prostu nie rób tego.
użytkownik nieznany
3

Przenieś pliki, które chcesz zachować. Przejdź o jeden poziom wyżej, usuń folder. Utwórz ponownie folder i przenieś te pliki z powrotem.

alex
źródło
Zastanawiam się, dlaczego minus? .. Jest to w rzeczywistości zarówno łatwiejsze, jak i bezpieczniejsze niż cokolwiek proponowanego przez innych: po prostu nie możesz strzelić sobie w stopę, naciskając specjalny znak w nazwie pliku.
alex
a) Przenosisz plik X jeden katalog w górę, gdzie istnieje plik X - po cichu usunięty, zniknął. b) Jesteś w najlepszym katalogu, w którym nie ma „up”. c) Jesteś w swoim domu, i nie ma uprawnień do zapisu w katalogu / home. Jeśli umieścisz swoją radę w skrypcie i przetestujesz ją bez problemu i wykorzystasz w takiej sytuacji - peng!
użytkownik nieznany
2
a) Hej, czy powiedziałem „przenieś pliki o jeden poziom wyżej ”? Powiedziałem, odsuń je. b) Więc próbujesz usunąć wszystkie pliki /, heh? Niezbyt praktyczne. c) Próba usunięcia wszystkich plików z twojego pliku również $HOMEnie jest zbyt praktyczna.
alex
Masz rację, przepraszam.
użytkownik nieznany
0

To właśnie skonfigurowałem jako skrypt .sh dla haka do wylogowywania OSX / MacOS, działa wystarczająco dobrze.

#! /bin/bash
for dir in /PathToFolder/*
 do
    if [ ! "$dir" = "/PathToFolder/FolderToKeep1" ] && [ ! "$dir" = "/PathToFolder/FolderToKeep2" ] && [ ! "$dir" = "/PathToFolder/FolderToKeep3" ] && [ ! "$dir" = "/PathToFolder/FolderToKeep4" ] && [ ! "$dir" = "/PathToFolder/FolderToKeep5" ] && [ ! "$dir" = "/PathToFolder/FolderToKeep6" ] ; then 
      echo ${dir}
      sudo rm -R $dir user
      dscl . -delete $dir
    fi 
  done

exit 0
ICMP
źródło
0

Za pomocą GNU-find możesz użyć przełącznika -delete, który usuwa również katalogi, jeśli są również puste:

 find tmp -not -name X -not -name Y -not -name Z -delete 
nieznany użytkownik
źródło
Jeśli X, Y lub Z to katalog, spowoduje to również usunięcie plików w nim zawartych. find tmp -maxdepth 1 -not -name X -not -name Y -not -name Z -deletejest jednym ze sposobów obejścia tego.
Gilles „SO- przestań być zły”
Ponieważ foldery w Uniksie są plikami (wszystko jest plikiem), być może to jest zamierzone. Pytanie wyraźnie mówi: „Mam wiele plików i folderów w określonym folderze i chcę je wszystkie usunąć;” - a jeśli chcesz wykluczyć Y, być może wiesz, czy Y jest katalogiem, czy nie.
użytkownik nieznany
Skończy się to również usunięciem, tmpjeśli nie będzie w nim plików X/ Y/ Z. Uwaga !jako standardowy odpowiednik GNU -not( -deletejest także rozszerzeniem GNU)
Stéphane Chazelas,
@ StéphaneChazelas: Z pytania wynika, że ​​poproszono o usunięcie folderów (wszystkich). Ponieważ huk wymaga maskowania, wolę pisać - nie. Może zależeć od niemieckiego układu klawiatury, gdzie Backslash wymaga Alt-Gr.
użytkownik nieznany