Você pode usar find com predicados negados para isso. Basicamente, faça um comando que encontre todos os arquivos que você deseja manter, negue a (s) condição (ões) correspondente (de tal forma que ela agora corresponda aos arquivos que você não quer manter), e diga para excluir esses arquivos ou simplesmente movê-los para fora do caminho.
Por exemplo, este comando irá imprimir uma lista de todos os arquivos sob o diretório atual, incluindo os subdiretórios, que têm nomes que terminam em .h :
find . -type f -name '*.h' -print
(O -type f restringe a correspondência apenas a arquivos regulares; não a diretórios, nós de dispositivos e assim por diante. A citação em torno de *.h é importante.)
Agora, inverta a condição de nome para imprimir todos os arquivos que não possuem nomes que terminem em .h :
find . -type f -not -name '*.h' -print
(Observe que -not não é compatível com POSIX, mas é mais limpo aqui, pois não requer escape de shell. Você também pode usar o padrão POSIX ! , mas pelo menos o bash exige que ! seja escapou.)
Quando estiver satisfeito que a lista de arquivos corresponde ao que você deseja excluir, basta substituir -print por -delete para excluir os arquivos. Ou, se você precisar de uma solução POSIX (novamente), poderá usar -exec rm '{}' '+' em vez de -delete , ao custo de invocar rm um número desconhecido de vezes.