TL; DR: a melhor maneira é usar em -exec rmvez de -delete.
find a \( -name b -prune \) -o -type f -exec rm {} +
Explicação:
Por que encontrar reclamar quando você tentar usar -deletecom -prune?
Resposta curta: porque -deleteimplica -depthe -depthtorna -pruneineficaz.
Antes de chegarmos à resposta longa, observe primeiro o comportamento de encontrar com e sem -depth:
$ find foo/
foo/
foo/f1
foo/bar
foo/bar/b2
foo/bar/b1
foo/f2
Não há garantia sobre o pedido em um único diretório. Mas há uma garantia de que um diretório seja processado antes de seu conteúdo. Anote foo/antes de qualquer foo/*e foo/barantes de qualquer foo/bar/*.
Isso pode ser revertido com -depth.
$ find foo/ -depth
foo/f2
foo/bar/b2
foo/bar/b1
foo/bar
foo/f1
foo/
Observe que agora todos foo/*aparecem antes foo/. O mesmo com foo/bar.
Resposta mais longa:
-pruneimpede que a localização desça para um diretório. Em outras palavras, -prunepula o conteúdo do diretório. No seu caso, -name b -pruneimpede que a localização desça para qualquer diretório com o nome b.
-depthfaz encontrar para processar o conteúdo de um diretório antes do próprio diretório. Isso significa que no momento em que a find processa a entrada do diretório, bseu conteúdo já foi processado. Assim -pruneé ineficaz com -depthefeito.
-deleteimplica -depthque ele possa excluir os arquivos primeiro e depois o diretório vazio. -deletese recusa a excluir diretórios não vazios. Eu acho que seria possível adicionar uma opção para forçar -deletea exclusão de diretórios não vazios e / ou impedir -deletea implicação -depth. Mas isso é outra história.
Há outra maneira de conseguir o que você deseja:
find a -not -path "*/b*" -type f -delete
Isso pode ou não ser mais fácil de lembrar.
Este comando ainda desce para o diretório be processa todos os arquivos nele apenas para -notrejeitá-los. Isso pode ser um problema de desempenho se o diretório bfor enorme.
-pathfunciona de forma diferente do que -name. -namecorresponde apenas ao nome (do arquivo ou diretório) enquanto -pathcorresponde ao caminho inteiro. Por exemplo, observe o caminho /home/lesmana/foo/bar. -name -barcorresponderá porque o nome é bar. -path "*/foo*"corresponderá porque a cadeia /fooestá no caminho. -pathtem alguns meandros que você deve entender antes de usá-lo. Leia a página do manual findpara mais detalhes.
Cuidado que isso não é 100% infalível. Há chances de "falsos positivos". A maneira como o comando é escrito acima irá pular qualquer arquivo que possua qualquer diretório pai cujo nome esteja começando com b(positivo). Mas também ignorará qualquer arquivo cujo nome esteja começando, bindependentemente da posição na árvore (falso positivo). Isso pode ser corrigido escrevendo uma expressão melhor que "*/b*". Isso é deixado como um exercício para o leitor.
Presumo que você usou ae bcomo espaços reservados e os nomes reais são mais parecidos com allosauruse brachiosaurus. Se você colocar brachiosaurusno lugar b, a quantidade de falsos positivos será drasticamente reduzida.
Pelo menos os falsos positivos será não excluído, por isso vai ser não tão trágico. Além disso, você pode verificar se há falsos positivos executando primeiro o comando sem -delete(mas lembre-se de colocar o implícito -depth) e examine a saída.
find a -not -path "*/b*" -type f -depth
amenosa/b?