find -delete nie usuwa niepustych katalogów

32

Komenda

$ find ~ -name .DS_Store -ls -delete

działa na Mac OS X, ale

$ find ~ -name __pycache__ -type d -ls -delete

nie - katalogi zostały odnalezione, ale nie usunięte.

Czemu?

PS. Wiem, że mogę

$ find ~ -name __pycache__ -type d -ls -exec rm -rv {} +

pytanie brzmi, dlaczego find -delete ma nie działać.

sds
źródło

Odpowiedzi:

36

find„s -deleteflag działa podobnie jak rmdirpodczas usuwania katalogów. Jeśli katalog nie jest pusty po osiągnięciu, nie można go usunąć.

Najpierw musisz opróżnić katalog. Ponieważ określasz -type d, findnie zrobię tego za ciebie.

Możesz rozwiązać ten problem, wykonując dwa przejścia: najpierw usuń wszystko w nazwanych katalogach __pycache__, a następnie usuń wszystkie katalogi o nazwie __pycache__:

find ~ -path '*/__pycache__/*' -delete
find ~ -type d -name '__pycache__' -empty -delete

Nieco mniej ściśle kontrolowane, ale w jednej linii:

find ~ -path '*/__pycache__*' -delete

Spowoduje to usunięcie wszystkiego, co ma miejsce w domu __pycache__.

GnP
źródło
Po znalezieniu 4.4.2 ta ostatnia komenda musi być find ~ -path '*/__pycache__*' -deletelub prawdopodobnie find ~ -path '*/__pycache__/*' -o -name __pycache__ -deletemusi być bezpieczna.
naught101
3
@ naught101, że powinno być find ~ \( -path '*/__pycache__/*' -o -name __pycache__ \) -deletejak i ma pierwszeństwo przed lub .
Stéphane Chazelas
6

Istnieje kilka potencjalnych przyczyn tego.

1) Powiedziałeś, aby usunąć tylko katalogi ( -type d), a te katalogi nadal mają w sobie pliki.

2) Twoje katalogi zawierają tylko inne katalogi, więc -type dzajmie się kwestią zawartości. Jednak używasz OS-X, który jest w dużej mierze oparty na FreeBSD, a FreeBSD finddomyślnie przetwarza katalog przed jego zawartością.
Istnieje jednak -depthopcja rozwiązania tego problemu poprzez nakazanie findprzetworzenia katalogu po jego zawartości.

find ~ -name __pycache__ -type d -ls -delete -depth

Ten problem nie występuje w systemie Linux, ponieważ -deleteopcja domyślnie włącza -depth.

 

FreeBSD man 1 find:

 -depth  Always true; same as the non-portable -d option. Cause find to
   perform a depth-first traversal, i.e., directories are visited in
   post-order and all entries in a directory will be acted on before
   the directory itself. By default, find visits directories in
   pre-order, i.e., before their contents. Note, the default is not
   a breadth-first traversal.

GNU man 1 find:

 -depth Process each directory's contents before the directory itself. The -delete
        action also implies -depth.
Patrick
źródło
2
Tak, ale znalezisko FreeBSD (1) mówi: -delete„Ta opcja implikuje przetwarzanie w pierwszej kolejności”. GNU find (1) mówi: „… -delete oznacza -głębość ,…”, więc nie powinno konieczne jest dodanie -depthdo polecenia.
G-Man mówi „Przywróć Monikę”
1
Z strony findpodręcznika GNU : „Aby uniknąć nieporozumień, opcje globalne powinny być określone w wierszu poleceń za listą punktów początkowych, tuż przed pierwszym testem, opcją pozycyjną lub akcją. Jeśli podasz opcję globalną w innym miejscu, find znajdzie wyślij komunikat ostrzegawczy wyjaśniający, że może to być mylące ”. Teraz -deletejest „globalną opcją” po ~wydanym poleceniu. Zauważyłem również, że nie ma znaczenia, czy dodasz, -depthczy nie. Niepuste katalogi pozostają niewykryte (ale to prawdopodobnie dlatego, że ja -maxdepthteż używam )
David Tonhofer,