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.