Wyklucz jeden wzór z dopasowania globalnego

53

Mam kilka plików o tej samej podstawowej nazwie pliku. Chciałbym usunąć wszystkie oprócz jednego

foo.org #keep
foo.tex #delete
foo.fls #delete
foo.bib #delete
etc

Gdybym nie musiał go mieć, wiem, że mógłbym go użyć rm foo.*.

TLDP demonstruje ^zanegowanie dopasowania. Dzięki próbom i błędom udało mi się to znaleźć

rm foo.*[^org]

robi to, czego potrzebuję, ale tak naprawdę nie rozumiem składni.

Ponadto, chociaż nie jest to ograniczenie w moim przypadku użycia, myślę, że ten wzór również ignoruje foo.oi foo.or. Jak działa ten wzorzec i jak wyglądałby glob ignorujący tylko foo.org ?

jake
źródło
1
Jako dodatek do @glen odpowiedzieć warto wspomnieć, że rm foo.*[^org]usuwa wszystkie pliki, których ostatnia postać jest ani o, ralbo g, więc foo.foonie pasuje albo.
jimmij
Używasz Regular Expression. Powinieneś uważać na swoje postacie grupujące. Za pomocą wsporników już podano klasy znaków sens, że chcesz usunąć wszystkie pliki, które miały rozszerzenie z literami o, ralbo gw dowolnej kolejności. Użyj nawiasu, aby utworzyć grupę i zachować kolejność znaków.
Pan Mascaro
3
@ jbarker2160 - to nie jest tak naprawdę wyrażenie regularne, częściej nazywane jest glob (lub wzorzec nazwy pliku ), który jest mniej więcej podzbiorem wyrażenia regularnego - zobacz sekcję dotyczącą dopasowania wzorca strony podręcznika bash, aby uzyskać szczegółowe informacje. Jego wzorzec foo.*[^org]będzie pasował do każdej nazwy pliku, która zaczyna się foo.od jednego lub więcej znaków po kropce, gdzie ostatnim znakiem nie jest o, r lub g. Tak by pasowało foo.orb, ale nie foo.orglub foo.orlub foo.o. Odpowiedź GlennJackman pokazuje, jak włączyć funkcje rozszerzonego dopasowywania wzorca, aby negować dopasowanie.
Johnny

Odpowiedzi:

23

W bash możesz także użyć GLOBIGNORE="*.org"; rm -i foo*.

A unset GLOBIGNOREkiedy skończone.

To nie jest tak naprawdę lepsze niż shopt -s extglob, ale łatwiej mi zapamiętać.

mivk
źródło
5
@ Ruslan To nie działa. Powinieneś to zrobić( GLOBIGNORE="*.org"; rm -i foo* )
DBedrenko,
3
Uwaga: jeśli chcesz rozwinąć listę ignorowanych, oddziel je dwukropkiem, np.GLOBIGNORE="*foo*:*bar*"
phyatt
7

Rura może zrobić?

ls * | grep -v "foo.org" | xargs -I {} echo {}

(oczywiście możesz chcieć zastąpić echo rm w ostatnim łańcuchu).

Cegła suszona na słońcu
źródło
Przydatne w razie potrzeby w jednym wierszu.
bruceskyaus
1
Łatwiejsze do zapamiętania (dla mnie często to robię) i pozwala na bardziej skomplikowane przetwarzanie do uruchomienia :)
drevicko
1
ls -1powinien być bardziej niezawodny, aby mieć pewność, że wszystkie pliki są obsługiwane greposobno
MichaelChirico
0

OP był bardzo blisko:

rm foo.*[^o][^r][^g]

choć w tym przypadku nie *jest to konieczne.

MrMas
źródło