Istnieje wiele sytuacji, w których użycie a *
jest praktycznie nieuniknione - np. rm -rf *
W folderze zawierającym tysiące podfolderów i plików.
Ale co, jeśli chcesz wykluczyć tylko jeden lub dwa pliki lub foldery z rm
polecenia? Przeszukiwałem swoją stronę i znalazłem tylko dość skomplikowane rozwiązania, jak find . -depth -not \( -name 'one' -o -name 'two' \
-o -name 'three' \) -exec rm {} \;
podano tutaj .
Czy można to zrobić w łatwiejszy sposób - bez tego objazdu find
? Np. rm -rf --exclude='one' --exclude='two' --exclude='three' *
Jak w rsync czy po prostu rm -rf -e 'one','two','three' *
?
Może nawet ogóle możliwość wyłączenia rzeczy z *
(tak jak inne polecenia cp
, mv
... nie trzeba zaimplementować własną rękę)? Coś w *{'one','two','three'}
tym stylu?
źródło
find
z tej--delete
opcji (nie trzeba wykonywaćrm
dla każdego pliku. To niepotrzebny narzut).mv -t /tmp one two three && rm -rf * && mv -t . /tmp/one /tmp/two /tmp/three
, ale wolałbym rozwiązanie dające możliwość wyraźnego wykluczenia czegoś z*
. Z pewnością będą sytuacje, w których przenoszenie lub kopiowanie plików do innego miejsca docelowego nie będzie możliwe.Odpowiedzi:
W przypadku Bash dostępna jest opcja powłoki,
extglob
która jest domyślnie wyłączona, aby zachować zgodność ze standardową składnią powłoki. Extglob uzupełnia składnię dodatkowymi operatorów takich jak!()
,?()
,@()
i kilka innych.Aby włączyć
extglob
, wpiszshopt -s extglob
. Aby pozostawić włączone dla bieżącego typu użytkownikaecho 'shopt -s extglob' >> ~/.bashrc
.Na przykład rm: Z
extglob
można użyćźródło
shopt
coś do siebie~/.bashrc
, to nie zaszkodzi.*
, ale dodaje podobne wskaźniki (takie jak!
), które mają dodatkowe funkcje? W takim przypadku byłoby to cudowne rozwiązanie.Zbudowałem z wyjątkiem tego (proszę, że nie byłem jeszcze w stanie dodać dokumentacji).
Mam folder podobny do następującego:
Pisanie
except b d
da cia
ic
Teraz możesz to potokować
rm
.Może to być trudne do zapamiętania, więc dlaczego po prostu nie zbudować skryptu oprócz wyjątku o nazwie
rm-except
:Podobnie łatwe jest
ls-except
:źródło
Jako alternatywę dla extglob (choć jest to bardzo dobra odpowiedź i każdy powinien mieć
shopt -s extglob globstar
w swoim .bashrc), możesz użyć zmiennej globalnej $ GLOBIGNORE . Powiedzmy, że chcesz pobrać każdy plik oprócz „foo.txt” i „bar baz.txt”:... spowoduje to jednak włączenie opcji powłoki
dotglob
, co oznacza, że*
dopasuje pliki zaczynające się od kropki (które zwykle są ukryte). Tak naprawdę potrzebujesz dwóch poleceń:Ponieważ jest to zmienna globalna, wpłynie na każdy używany glob, dopóki $ GLOBSTAR nie zostanie rozbrojony przez wylogowanie lub za pomocą
Działa także tylko na ciągach literalnych przekazywanych do zmiennej. Możesz zobaczyć, co mam na myśli, ustawiając $ GLOBIGNORE i patrząc na różnicę między tymi poleceniami:
źródło