W Linuksie, jak usunąć wszystkie pliki Z WYJĄTKIEM wzoru * .txt?

73

Wiem, jak usunąć cały txtplik z bieżącego katalogu przez rm *.txt. Czy ktoś wie, jak usunąć wszystkie pliki w bieżącym katalogu z wyjątkiem txtpliku?

Pistolet pożarowy
źródło
20
Jak zawsze, sprawdź podane odpowiedzi za pomocą nieszkodliwego polecenia, tak jak lsprzed faktyczną próbą połączenia rm.
chepner

Odpowiedzi:

111

Możesz użyć find:

find . -type f ! -name '*.txt' -delete

Lub rozszerzone funkcje globowania bash:

shopt -s extglob
rm *.!(txt)

Lub w Zsh:

setopt extendedglob
rm *~*.txt(.)
#  ||     ^^^ Only plain files
#  ||^^^^^ files ending in ".txt"
#  | \Except
#   \Everything
Kevin
źródło
Niektóre z nich mogą wymagać dostosowania w zależności od tego, czy masz foldery i co chcesz z nimi zrobić.
Kevin
1
Nie powinno *.!(txt)być !(*.txt)?
Lri,
@LauriRanta zależy od tego, co znajduje się w folderze, na który nie otrzymaliśmy odpowiedzi. Jest w porządku, tak jakby wszystkie pliki miały rozszerzenia i rmdusiłyby się, gdyby były foldery.
Kevin
Mam problem z nawiasami. Kiedy używam stylu globowania w skrypcie bash, narzeka on na błąd składniowy i nawiasy. Działa to jednak z poziomu interfejsu CLI.
CMCDragonkai
1
@izogfif sprawdź, czy to find . -type f ! -name "*.txt" | xargs -r rmzadziała w GNU \ xargs. Komenda xargs w BSD i UNIX może nie mieć -r musisz sprawdzić swój lokalnyman xargs
Ntwobike
10

Jeśli chcesz tylko usunąć wszystkie pliki oprócz „* .txt”, możesz użyć następującego polecenia:

$ find . -type f ! -name "*.txt" -exec rm -rf {} \;

ale jeśli chcesz również usunąć katalogi wraz z plikami, możesz użyć tego:

$ find . ! -name "*.txt" -exec rm -r {} \;

Sagar Rakshe
źródło
9

można to zrobić na wiele sposobów. ale najprostszym sposobem byłoby (bash):

shopt -s extglob
rm !(*.txt)
Kent
źródło
4

Jedno rozwiązanie bez find:

mv dir/*.txt otherdir/
rm -r dir
mv otherdir dir

To powinno działać na wszelkiego rodzaju powłokach.

michas
źródło
3

Możesz użyć odwróconego grep i xargs

ls | grep -v .txt$| xargs rm
rjv
źródło
ls | grep -v *.txt | xargs rmdziała równie dobrze
Phillipsk
@phillipsk grep -v *.txtbędzie działać tylko wtedy, gdy będzie dokładnie jeden .txtplik. Jeśli nie ma, grepużyje *.txtjako wzorca; jeśli jest więcej niż jeden, wyszuka pierwszą nazwę pliku we wszystkich pozostałych .txtplikach, ignorując dane wyjściowe z ls. (Dokładne wyniki mogą zależeć od opcji globu powłoki).
JigglyNaga,
.txt$dopasuje ciągi znaków kończące się txtniezależnie od kropki. Ponieważ grepjako wyrażenie przyjmuje wyrażenie regularne. Więc pliki a.txti aatxta a-txtwszystko będzie towarzyszyć tej wypowiedzi. Prawidłowe wyrażenie powinno być ls | grep -v \\.txt$ | xargs --no-run-if-empty rm. Dla ciekawskich: jeśli chcesz bezpiecznie bawić się wyrażeniem, użyj tego wyrażenia testowego ls | grep \\.txt$ | xargs --no-run-if-empty echo(uwaga: nie ma -vflagi i rm=>echo). Uwaga 2: mogłeś zauważyć podwójny ukośnik odwrotny. Jeden służy do wyrażenia regularnego, drugi do basha, aby uniknąć ukośnika.
Dimitry K,
1

Po prostu wykonaj:

rm $(ls -I "*.txt" ) # Usuwa typ pliku oprócz * .txt

Podobnie, jeśli trzeba usunąć „oprócz jednego lub więcej typów plików”, wykonaj:

rm $(ls -I "*.txt" -I "*.pdf" ) # Usuwa typy plików oprócz * .txt i * .pdf

Surya
źródło
Witamy w StackExchange! Ta -Iopcja może być przydatna, ale zobacz, dlaczego nie przeanalizować ls . A co | xargsosiąga? Bez żadnych argumentów po prostu działa echona wszystkich danych wejściowych.
JigglyNaga
Co xargsma osiągnąć?
wtorek
Dzięki, xargs nie był użyteczny w powyższym przypadku, teraz poprawione.
Surya,
0

Działa to również w celu usunięcia wszystkich ukrytych plików (kropek) i folderów, z wyjątkiem jednego ( .mydir):

rm -rf $(ls -aI ".mydir")
Chetabahana
źródło