Odpowiedzi:
cd <the directory you want>
find . -type f ! -iname "*.pdf" -delete
.pdf
w nazwie plikuNa przykład, jeśli temp
w twoim katalogu domowym znajduje się katalog:
cd ~/temp
następnie usuń pliki:
find . -type f ! -iname "*.pdf" -delete
Spowoduje to usunięcie wszystkich plików oprócz xyz.pdf
.
Możesz połączyć te dwa polecenia, aby:
find ~/temp -type f ! -iname "*.pdf" -delete
.
jest bieżącym katalogiem. !
oznacza zabranie wszystkich plików oprócz tych .pdf
na końcu. -type f
wybiera tylko pliki, a nie katalogi. -delete
oznacza go usunąć.
!
musi przyjść wcześniej -name
. po prostu -name
będzie zawierać tylko .pdf
, podczas gdy -iname
będzie zawierać zarówno .pdf
i.PDF
Aby usunąć tylko w bieżącym katalogu, a nie w podkatalogach, dodaj -maxdepth 1
:
find . -maxdepth 1 -type f ! -iname "*.pdf" -delete
.
oznacza bieżący katalog. !
oznacza, że weźmiesz wszystkie pliki oprócz tego .pdf
na końcu. -delete
oznacza go usunąć. czy jestem teraz czysty?
-maxdepth 1
parametr na początek. Następnie zasugeruj usunięcie parametru, jeśli chcesz usunąć rekurencyjnie.
Dzięki bash
rozszerzeniu globowania powłoki możesz usunąć wszystkie pliki z rozszerzeniami innymi niż .pdf
za pomocą
rm -- *.!(pdf)
Jak zauważono w @pts, --
znaki wskazują koniec dowolnych opcji poleceń, dzięki czemu polecenie jest bezpieczne w rzadkich przypadkach plików, których nazwy zaczynają się od -
znaku.
Jeśli chcesz usunąć pliki bez żadnego rozszerzenia, a także pliki z rozszerzeniami innymi niż .pdf
, to jak wskazał @DennisWilliamson, możesz użyć
rm -- !(*.pdf)
Rozszerzone globowanie powinno być domyślnie włączone, ale jeśli nie, możesz to zrobić za pomocą
shopt -s extglob
Zwłaszcza, jeśli zamierzasz użyć tego w skrypcie, ważne jest, aby pamiętać, że jeśli wyrażenie nie pasuje do niczego (tj. Jeśli w katalogu nie ma plików innych niż pdf), wówczas domyślnie glob zostanie przekazany do pliku rm
polecenie, co powoduje błąd podobny do
rm: cannot remove `*.!(pdf)': No such file or directory
Możesz zmodyfikować to domyślne zachowanie za pomocą nullglob
opcji powłoki, jednak ma to swój problem. Aby uzyskać dokładniejszą dyskusję, zobacz NullGlob - Wiki Grega
rm *~*.pdf
!(*.py)
. Prawdopodobnie, jeśli OP chce pozostać tylko plikami „.pdf”, pliki bez rozszerzeń również powinny zostać usunięte i nie powinny być ignorowane.
$ cd <the directory you want>
$ gvfs-trash !(*.pdf)
Lub za pomocą mv
polecenia (ale w ten sposób nie można przywrócić go z Kosza, ponieważ nie rejestruje on informacji .trashinfo, więc oznacza to, że przeniesiono pliki do miejsca docelowego, w którym znajduje się poniżej).
mv !(*.pdf) ~/.local/share/Trash/files
rm
.
Najłatwiejsze podejście: Utwórz gdzieś inny katalog (jeśli usuwasz tylko w jednym katalogu, a nie rekurencyjnie, może to być nawet podkatalog); przenieś tam wszystkie pliki .pdf; usuń wszystko inne; cofnij plik pdf do tyłu; usuń katalog pośredni.
Szybko, łatwo, możesz dokładnie zobaczyć, co robisz. Upewnij się tylko, że katalog pośredni znajduje się na tym samym urządzeniu co katalog, który czyścisz, aby ruchy były nazwami, a nie kopiami!
Użyj GLOBIGNORE bash:
GLOBIGNORE=x.pdf:a.pdf
rm *
unset GLOBIGNORE
Ze strony podręcznika użytkownika bash:
GLOBIGNORE: Rozdzielona dwukropkami lista wzorców definiujących zestaw nazw plików, które mają zostać zignorowane przez rozwinięcie nazwy ścieżki.
Szybki test:
mkdir /tmp/foooooo
cd /tmp/foooooo
touch x.pdf y.zip z.mp3 a.pdf
GLOBIGNORE=x.pdf:a.pdf
ls -1 *
Wynik:
y.zip z.mp3
Oto podejście mi się podoba, bo to pozwala mi być bardzo ostrożny: komponować sposób, aby pokazać tylko te pliki, które chcę usunąć, a następnie wysłać je do rm
korzystania xargs
. Na przykład:
ls
pokazuje mi wszystkols | grep pdf
pokazuje mi pliki, które chcę zachować. Hmmls | grep -v pdf
pokazuje coś przeciwnego: wszystko oprócz tego, co chcę zachować. Innymi słowy, pokazuje listę rzeczy, które chcę usunąć. Mogę to potwierdzić, zanim zrobię coś niebezpiecznego.ls | grep -v pdf | xargs rm
wysyła dokładnie tę listę do rm
usunięciaJak powiedziałem, podoba mi się to przede wszystkim ze względu na bezpieczeństwo: nie przypadek rm *
dla mnie. Dwie inne zalety:
ls
lub, find
aby uzyskać początkową listę, jak wolisz. Możesz zawęzić wszystko, co chcesz, w trakcie zawężania tej listy - inną grep
, inną awk
lub cokolwiek innego. Jeśli chcesz usunąć tylko pliki, których nazwy zawierają kolor, możesz zbudować go w ten sam sposób.find
do wyszukiwania i rm
usuwania, zamiast pamiętać, że find
akceptuje -delete
flagę. A jeśli to zrobisz, ponownie możesz skomponować alternatywne rozwiązania; może zamiast tego rm
możesz utworzyć trash
polecenie, które przenosi plik do kosza (umożliwiając „usunięcie”) i potokuje do niego zamiast rm
. Nie potrzebujesz find
obsługi tej opcji, po prostu do niej potokujesz.Zobacz komentarze @pabouk, aby dowiedzieć się, jak to zmienić, aby obsługiwać niektóre przypadki krawędzi, takie jak podziały linii w nazwach plików, nazwy plików my_pdfs.zip
itp.
pdf
dowolne miejsce w jego nazwie. --- b) Usunie pliki PDF, jeśli dowolna litera w sufiksie jest wielka. --- c) Nie jest dobrym pomysłem używanie wyjścia ls
. Nie będzie działać z nazwami plików zawierającymi znaki nowej linii. Niektóre implementacje ls
zamiany znaków specjalnych, np. Tab by ?
. --- Lepiej jest użyć: find -maxdepth 1 -print0
. (nie tak krótki jak ls
:) ----- Aby rozwiązać a) ib) użyj grep -vi '\.pdf$'
--- kompletne (ale tylko GNU) rozwiązanie:find -maxdepth 1 -print0 | grep -viz '\.pdf$' | xargs -0 rm
| head -20
przynajmniej sprawdzić, czy wygląda mniej więcej poprawnie, a jeśli tak rm my_pattern
, nie masz szansy na zauważenie dużego błędu.
find . -type f ! -name "*.pdf"
do drukowania na konsoli, lub potokuj do mniejszej lub pliku. [a następnie potokuj do xargs do rm, jeśli chcesz, tak jak komentarze pabouk (z -print0 | ... -0 dla dziwnych nazw plików)]
Zwykle rozwiązuję takie problemy z interaktywnego interpretera Pythona:
mic@mic ~ $ python
>>> import os
>>> for f in os.listdir('.'):
... if not f.endswith('.pdf'):
... os.remove(f)
Może być dłuższy niż jednowarstwowy z find
lub xargs
, ale jest bardzo odporny i wiem dokładnie, co robi, bez konieczności wcześniejszego badania.
for item in [f for f in os.listdir('.') if not f.endswith('.pdf')]: os.remove(item)
python -c "import os; for f in os.listdir('.'): if not f.endswith('.pdf'): os.remove(f)"
[os.remove(f) for f in os.listdir('.') if not f.endswith('.pdf')]
lepszą odpowiedzią (w porównaniu do mojej poprzedniej odpowiedzi) na to pytanie będzie użycie potężnego file
polecenia.
$ file -i abc.pdf
abc: application/pdf; charset=binary
teraz twój problem:
cd <the directory you want to search in>
for var in ./*
do
if file -i "$var" | grep -q 'application/pdf\;'
then
echo "$var"
fi
done
zadaniem for
polecenia jest podanie plików w bieżącym katalogu w postaci zmiennej $var
. if-then
polecenie wyświetla nazwy plików pdf, biorąc status wyjścia 0
z file -i "$var" | grep -q 'application/pdf\;'
polecenia, daje status wyjścia 0
tylko wtedy, gdy znajdzie pliki pdf.
rm $(ls -lo|grep -v [Pp][Dd][Ff]$|awk '{print $7}')
Ostrzeżenie! Lepiej najpierw spróbuj
ls -l $(ls -lo|grep -v [Pp][Dd][Ff]$|awk '{print $7}')
-i
z grep
do dopasowywania bez rozróżniania wielkości liter.
rm -i -- !(*@(a|x).pdf)
Czytaj jako, usuń wszystkie pliki, które nie są a.pdf
lub x.pdf
.
Działa poprzez wykorzystanie 2 wydłużonych globs zewnętrzna !()
negacji zawartego glob, który z kolei wymaga, aby do wzorca, musi być zgodny z jednym lub więcej a
lub x
stanie przed .pdf
końcówką. Zobacz glob # extglob .
$ ls -a
.dotfile1 .dotfile2 a.pdf x.pdf y.zip z.mp3
$ echo -- !(a.pdf)
-- x.pdf y.zip z.mp3
$ echo -- !(x.pdf)
-- a.pdf y.zip z.mp3
$ echo -- !(a.pdf|x.pdf)
-- y.zip z.mp3
$ echo -- !(@(a|x).pdf) # NOTE.that this matches the .dotfiles* as well
-- . .. .dotfile1 .dotfile2 y.zip z.mp3
$ echo -- !(*@(a|x).pdf) # but this doesn't
-- y.zip z.mp3
$ echo rm -i -- !(*@(a|x).pdf)
rm -i -- y.zip z.mp3
$ ksh -c 'for i in ./*; do case $i in *.pdf)continue;; *)rm "$i";; esac;done'
Dość dużo POSIX i kompatybilny z dowolnym powłoce Bourne'a Style ( ksh
, bash
, dash
). Dobrze nadaje się do przenośnych skryptów i gdy nie możesz użyć bash
rozszerzonego globowania powłoki.
$ perl -le 'opendir(my $d,"."); foreach my $f (grep(-f && !/.pdf/ , readdir($d))){unlink $f};closedir $d'
Lub nieco czystszy:
$ perl -le 'opendir(my $d,"."); map{ unlink $_ } grep(-f "./$_" && !/.pdf/ , readdir($d));closedir $d'
python -c 'import os;map(lambda x: os.remove(x), filter(lambda x: not x.endswith(".pdf"),os.listdir(".")))'
Uważaj na to, co usuwasz!
Bezpiecznym sposobem przetestowania go przed próbą usunięcia jest przetestowanie go najpierw ls
, ponieważ niektóre nieprzechwycone zachowania mogą usuwać niechciane pliki. Możesz to zrobić bezpośrednio poza katalogiem. ls
jest podobny do rm
, więc:
ls sub/path/to/files/!(*.pdf)
Spowoduje to wyświetlenie listy
y.zip
z.mp3
Teraz możesz zobaczyć, co usuwasz, i możesz je bezpiecznie usunąć:
rm sub/path/to/files/!(*.pdf)
I to wszystko. Możesz używać symboli wieloznacznych, *
aby być bardziej selektywnym, tak jak przechowywanie tylko dokumentów kursu programowania:
rm sub/path/to/files/!(*programming*)
.
oznacza „i”?!
oznacza „oprócz”-name
oznacza, że chcesz wykluczyć za pomocą parametru nazwy, a następnie-delete
czy należy podjąć działanie po znalezieniu? Więc szuka wszystkiego oprócz „* .pdf” i usuwa je? A może źle zrozumiałem?