Muszę cyklicznie przeglądać katalog i usunąć wszystkie pliki z rozszerzeniami .pdf
i .doc
. Udaje mi się cyklicznie przeglądać katalog, ale nie udaje mi się filtrować plików z wyżej wymienionymi rozszerzeniami plików.
Jak dotąd mój kod
#/bin/sh
SEARCH_FOLDER="/tmp/*"
for f in $SEARCH_FOLDER
do
if [ -d "$f" ]
then
for ff in $f/*
do
echo "Processing $ff"
done
else
echo "Processing file $f"
fi
done
Potrzebuję pomocy, aby ukończyć kod, ponieważ nigdzie nie dojdę.
rm
to część kodu OP, ale tak naprawdę nie ma związku z zadanym pytaniem. Myślę, że byłoby bezpieczniej, gdyby odpowiedzi zostały sformułowane za pomocą nieszkodliwego polecenia, takiego jakecho
.Odpowiedzi:
find
jest po prostu do tego stworzony.źródło
-delete
opcję.find ... -print0 | xargs -0 ...
, a nie surowego find | xargs, aby uniknąć problemów z nazwami plików zawierającymi znaki nowej linii.xargs
bez opcji jest prawie zawsze złą radą i nie jest to wyjątek. Użyjfind … -exec
zamiast tego.Jako uzupełnienie odpowiedzi mouviciel, możesz również zrobić to jako pętlę for, zamiast używać xargs. Często uważam, że xargs są uciążliwe, zwłaszcza jeśli w każdej iteracji muszę zrobić coś bardziej skomplikowanego.
Jak komentowało wiele osób, zakończy się to niepowodzeniem, jeśli w nazwach plików są spacje. Możesz obejść ten problem, tymczasowo ustawiając IFS (wewnętrzny separator pól) na znak nowej linii. To również kończy się niepowodzeniem, jeśli
\[?*
w nazwach plików znajdują się symbole wieloznaczne . Możesz to obejść, tymczasowo wyłączając ekspansję wieloznaczną (globbing).Jeśli w nazwach plików masz znaki nowej linii, to też nie zadziała. Lepiej Ci będzie z rozwiązaniem opartym na Xargs:
(Nawiasy ze znakami ucieczki są tutaj wymagane, aby mieć
-print0
zastosowanie do obuor
klauzul).Znajdowanie GNU i * BSD ma również
-delete
akcję, która wyglądałaby następująco:źródło
for f in $(find ...)
. Po prostu nie używaj tej metody.Bez
find
:/tmp/*
są plikami w katalogu i/tmp/**/*
są plikami w podfolderach. Możliwe, że musisz włączyć opcję globstar (shopt -s globstar
). Więc w przypadku pytania kod powinien wyglądać następująco:Zauważ, że wymaga to bash ≥4.0 (lub zsh bez
shopt -s globstar
lub ksh zset -o globstar
zamiastshopt -s globstar
). Co więcej, w bash <4.3, przemierza symboliczne dowiązania do katalogów, jak również katalogów, co zwykle nie jest pożądane.źródło
for f in /tmp/**
wystarczy. Zawiera pliki z katalogu / tmp dir.for f in /tmp/*.{pdf,doc} tmp/**/*.{,pdf,doc} ; do
**
jest ładnym rozszerzeniem, ale nie przenośnym do POSIXsh
. (To pytanie jest otagowane jako bash, ale fajnie byłoby wskazać, że w przeciwieństwie do kilku tutaj rozwiązań, to naprawdę jest tylko Bash. Lub, cóż, działa również w kilku innych rozszerzonych powłokach.)Jeśli chcesz coś zrobić rekurencyjnie, sugeruję użycie rekurencji (tak, możesz to zrobić używając stosów i tak dalej, ale hej).
To powiedziawszy,
find
jest prawdopodobnie lepszym wyborem, jak już sugerowano.źródło
Oto przykład użycia powłoki (
bash
):źródło
To nie jest bezpośrednią odpowiedzią na twoje pytanie, ale możesz rozwiązać swój problem za pomocą jednej linijki:
Niektóre wersje find (GNU, BSD) mają
-delete
akcję, której możesz użyć zamiast wywoływaniarm
:źródło
Ta metoda dobrze radzi sobie ze spacjami.
Edytuj, naprawia pojedynczo
źródło
Dla basha (od wersji 4.0):
To wszystko.
Końcowe rozszerzenie „.ext” służy do wybierania plików (lub katalogów) z tym rozszerzeniem.
Opcja globstar aktywuje ** (wyszukiwanie rekurencyjne).
Opcja nullglob usuwa *, gdy nie pasuje do żadnego pliku / katalogu.
Opcja dotglob zawiera pliki zaczynające się kropką (pliki ukryte).
Uważaj, zanim bash 4.3,
**/
również przemierza dowiązania symboliczne do katalogów, co nie jest pożądane.źródło
Następująca funkcja rekurencyjnie iteruje przez wszystkie katalogi w
\home\ubuntu
katalogu (cała struktura katalogów pod ubuntu) i stosuje niezbędne sprawdzenia welse
bloku.źródło
Oto najprostszy sposób, jaki znam:
rm **/@(*.doc|*.pdf)
**
sprawia, że działa to rekurencyjnie@(*.doc|*.pdf)
szuka pliku kończącego się na pdf LUB docŁatwy bezpiecznie przetestować zastępując
rm
zls
źródło
Nie ma powodu, aby potokować dane wyjściowe
find
do innego narzędzia.find
ma-delete
wbudowaną flagę.źródło
Pozostałe udzielone odpowiedzi nie będą obejmowały plików ani katalogów zaczynających się od. dla mnie zadziałało:
źródło
Po prostu zrób
źródło
Poniższe polecenie zapętli podany katalog rekurencyjnie i wyświetli całą zawartość:
for d in /home/ubuntu/*; do echo "listing contents of dir: $d"; ls -l $d/; done
źródło
ls -l /home/ubuntu/*/
, więc jest całkiem bezużyteczny.Jeśli możesz zmienić powłokę używaną do uruchomienia polecenia, możesz użyć ZSH do wykonania zadania.
Spowoduje to rekurencyjne zapętlenie wszystkich plików / folderów.
źródło