Odpowiedzi:
Oto proste rozwiązanie, którego prawdopodobnie powinieneś użyć:
mv filename.gif filename.gif.keep
rm *.gif
mv filename.gif.keep filename.gif
W tym .keep
rozszerzeniu nie ma nic specjalnego , dzięki czemu nazwa pliku tymczasowo się nie kończy .gif
.
Jeżeli nie musi zmienić nazwę pliku (i istnieje skryptów sytuacje, w których jest to ważne):
for X in *.gif; do
if [ "$X" != "filename.gif" ]; then
rm "$X"
fi
done
Możesz też napisać to krócej:
for X in *.gif; do [ "$X" != "filename.gif" ] && rm "$X"; done
Zamiast tego możesz użyć find
; to bardzo silny, to może rozważyć to bardziej czytelne i lepiej uchwyty dziwne nazwy plików z postaciami takimi jak *
na nich .
find . -maxdepth 1 -not -name 'filename.gif' -name '*.gif' -delete
Użyłem -not
operatora dla czytelności, ale jeśli zgodność z POSIX jest ważna - jeśli nie używasz GNU find, lub jeśli jest to skrypt, który zamierzasz rozpowszechniać wśród innych lub uruchamiać na różnych systemach - powinieneś !
zamiast tego użyj operatora:
find . -maxdepth 1 ! -name 'filename.gif' -name '*.gif' -delete
Jedną przydatną rzeczą find
jest to, że możesz łatwo zmodyfikować polecenie, aby nie rozróżniała wielkości liter, tak aby znajdowało i usuwało pliki z rozszerzeniami takimi jak .GIF
:
find . -maxdepth 1 -not -name 'filename.gif' -iname '*.gif' -delete
Pamiętaj, że użyłem -iname
zamiast -name
wzorca wyszukiwania, *.gif
ale go nie użyłem filename.gif
. Prawdopodobnie wiesz dokładnie, jak nazywa się Twój plik, i -iname
będzie pasował do naprzemiennej wielkości liter nie tylko w rozszerzeniu , ale w dowolnym miejscu w nazwie pliku.
Wszystkie te rozwiązania usuwają tylko pliki znajdujące się natychmiast w bieżącym katalogu . Nie usuwają plików nie zawartych w bieżącym katalogu i nie usuwają plików znajdujących się w podkatalogach bieżącego katalogu.
Jeśli chcesz usunąć pliki zawarte w bieżącym katalogu (tzn. W podkatalogach i podkatalogach tych podkatalogów itd. - pliki zawarte w bieżącym katalogu lub dowolnym z jego potomków), używaj find
bez maxdepth -1
:
find . -not -name 'filename.gif' -name '*.gif' -delete
Uważaj na to!
Możesz także ustawić inne wartości za pomocą -maxdepth
. Na przykład, aby usunąć pliki z bieżącego katalogu oraz jego dzieci i wnuków, ale nie głębiej:
find . -maxdepth 3 -not -name 'filename.gif' -name '*.gif' -delete
Tylko upewnij się, że nigdy nie stawiasz na -delete
pierwszym miejscu, przed innymi wyrażeniami! Zobaczysz, że zawsze umieszczam -delete
na końcu. Jeśli umieścisz go na początku, zostanie najpierw oceniony, a wszystkie pliki poniżej .
(w tym pliki, które się nie kończą .gif
i pliki w głębokich podkatalogach podrzędnych ... katalogów .
) zostaną usunięte!
Aby uzyskać więcej informacji , zobacz strony podręcznika dla bash
i sh
oraz do komend użytych w tych przykładach: mv
, rm
, [
, i (przede wszystkim) find
.
find
, która jest bardzo wszechstronna.
find
sobie z dziwnymi nazwami plików *
w nich lepiej niż w pętli for? Pętla for dobrze radzi sobie z plikami *
, ponieważ użyłeś podwójnych cudzysłowów.
Jeśli używasz bash
(domyślna powłoka), extglob
opcja powłoki umożliwia użycie rozszerzonej składni dopasowania wzorca. Aby go włączyć, użyj shopt
wbudowanego polecenia:
shopt -s extglob
(Uwzględniam ten wiersz w moim .bashrc
pliku).
Zapewnia między innymi dostęp do !()
operatora, który pasuje do dowolnego wzoru spoza parens. Do twojego celu:
rm !(filename).gif
Więcej informacji jest dostępnych w man bash
„Dopasowywanie wzorców”.
extglob
należy włączyć, ale nic złego się nie dzieje, jeśli jest wyłączone (w takim przypadku to po prostu nie działa). I wydaje się, że jest domyślnie włączony, nawet jeśli nie mam shopt -s extglob
żadnego z moich (lub globalnych) plików konfiguracyjnych. Jeśli istnieje proste wyjaśnienie, dlaczego to działa dla mnie po wyjęciu z pudełka, możesz dodać to do tej odpowiedzi; lub mogę opublikować nowe pytanie.
Otwórz terminal za pomocą Ctrl+ Alt+ Ti wpisz:
find . -type f -name "*.gif" -and -not -name "filename.gif" -exec rm -vf {} \;
Różnica między -delete
i -exec rm -vf {} \;
polega na tym, że dzięki drugiej opcji będziesz mógł zobaczyć, które pliki zostały usunięte z powodu -v
flagi. Tego nie da się zrobić z tą -delete
opcją. ( -name -delete
Wypisze nazwy plików, ale rm
z -v
objawia jeśli każdy plik został pomyślnie usunięty.)
Jest GLOBIGNORE
zmienna. Od man bash
:
GLOBIGNORE
A colon-separated list of patterns defining the set of filenames
to be ignored by pathname expansion. If a filename matched by a
pathname expansion pattern also matches one of the patterns in
GLOBIGNORE, it is removed from the list of matches.
Prostym sposobem jest po prostu ustawienie GLOBGINORE
nazwy pliku, o której mowa:
$ touch {a,b,c,d}.png
$ echo *.png
a.png b.png c.png d.png
$ GLOBIGNORE=c.png
$ echo *.png
a.png b.png d.png
W twoim przypadku:
GLOBIGNORE=filename.gif; rm *.gif
Oczywiście, ponieważ GLOBIGNORE
zawiera wzory, możesz go użyć, gdy chcesz wykluczyć wzór:
$ GLOBIGNORE='[a-c].png'; echo *.png
d.png
$ touch bd.png; GLOBIGNORE='?.png'; echo *.png
bd.png
Zaletą (?!) GLOBIGNORE
Jest to, że ustawienie to automatycznie wyklucza .
i nie..
jest dopasowywane oraz umożliwia dotglob
:
The GLOBIGNORE shell variable may be used to restrict the set of file‐
names matching a pattern. If GLOBIGNORE is set, each matching filename
that also matches one of the patterns in GLOBIGNORE is removed from the
list of matches. The filenames ``.'' and ``..'' are always ignored
when GLOBIGNORE is set and not null. However, setting GLOBIGNORE to a
non-null value has the effect of enabling the dotglob shell option, so
all other filenames beginning with a ``.'' will match. To get the old
behavior of ignoring filenames beginning with a ``.'', make ``.*'' one
of the patterns in GLOBIGNORE. The dotglob option is disabled when
GLOBIGNORE is unset.
Tak więc prosty sposób usuwania wszystkich plików i folderów w katalogu:
GLOBIGNORE=.; rm -r *
*
Dopasuje nazwy plików rozpoczynające się .
, gdyż GLOBIGNORE
włączone dotglob
, ale nie będzie pasować .
albo ..
, więc nie wpłynie na katalog nadrzędny w ten sposób.