Você pode executar basicamente qualquer operação ou lista de operações dentro da opção find -exec , então por que não untar de cada arquivo diretamente dentro de find -exec ? Para comandos complexos, é comum usar o recurso -exec para chamar um shell e usar a opção -c do comando shell para passar os comandos reais que você deseja executar. Por exemplo (na prática, há uma maneira muito mais simples de executar este exemplo real, mas é com o propósito de mostrar a ideia):
-exec sh -c 'mv "$1" "~/$1"' sh {} ';'
Isso iniciaria um shell para cada arquivo encontrado e faria com que ele movesse o arquivo para o diretório $HOME . Observe que o {} serve para passar o nome do arquivo encontrado como um parâmetro posicional do shell, isto é. $1 , portanto, no comando shell, $1 está sendo usado, não {} . No seu caso, uma solução desse tipo seria algo como:
-exec sh -c 'tar xvf "$1" -C "$(dirname $1)"' sh {} ';'
A idéia é que esse idioma traz todos os recursos do seu shell favorito dentro do comando find . (E, sim, você poderia usar bash ou zsh em vez de sh , apenas saiba que sh é carregado muito mais rápido e quando você está processando muitos arquivos, isso pode aumentar).
Se isso é algo que você faz repetidamente, ou você espera de antemão que a operação vai demorar muito tempo, AND você tem uma CPU multi-core, então pode ser benéfico para você considere uma segunda opção - conecte sua lista de arquivos ao GNU parallel e execute a operação untar simultaneamente em todos os núcleos. Tente isso para começar:
find . -name "*tar.gz" -type f -print0 |
parallel -0 tar xvf {} -C {//}
Como uma eficiência adicional, a resposta acima não precisa mais usar o comando dirname externo porque o GNU paralelo pode fazê-lo de maneira mais eficiente. Isso é o que o {//} está fazendo.
AVISO: Eu não sou especialista em parallel e estou oferecendo essa opção sem experiência real usando, por isso, se outras pessoas puderem conversar sobre se essa é a maneira correta, isso seria ótimo.