
Como fazer um loop recursivo através de um caminho e obter o último tar.gz
arquivo criado em cada diretório?
Quero executar tar -tvf file.tar.gz
no último arquivo criado em cada diretório
Todos os tar.gz
arquivos estão localizados no segundo nível de diretório. Portanto, a profundidade máxima do loop é 2
Este script imprimirá apenas cada diretório
cd $base_dir
find . -type d -printf '%f\n'
O diretório base é /var/www/bak
e todos os arquivos tar.gz estão localizados como
/var/www/bak/site1/www/file.tar.gz
/var/www/bak/site1/db/file.tar.gz
/var/www/bak/site2/www/file.tar.gz
/var/www/bak/site2/db/file.tar.gz
atualizar
find_tarballs (){
cd $base_dir
find . -name \*.tar.\* -execdir sh -c "echo -n \"\${PWD}/\"; ls -t *.tar.* | head -n 1" \; | sort -u -k1,1
}
filesize (){
ls -lh $1 | awk -F " " {'print $5'}
}
output="$(find_tarballs)"
set -- $output
shift
for tarball; do
echo "$tarball"
if [ ${tarball##*.} = 'gz' ]; then
list="$(tar -tzf $tarball)"
echo "Filesize: $(filesize $tarball), Files: $(echo "$list" | wc -l)\n"
echo 'Press ENTER to list files...'
read key
echo "$list"
else
echo "Filesize: $(filesize $tarball)"
fi
echo ''
done
Responder1
Supondo que seus caminhos não contenham espaços ou novas linhas:
find . -name \*.tar.\* -execdir sh -c "echo -n \"\${PWD} \"; ls -t *.tar.* | head -n 1" \; | sort -u -k1,1
encontrará todos os tarballs, executará o snippet de shell fornecido em cada diretório que contém e filtrará o resultado para que apenas um resultado seja mantido para cada diretório.
Para visualizar o conteúdo dos tarballs, supondo que seus nomes de arquivos também não contenham espaços ou novas linhas:
find . -name \*.tar.\* -execdir sh -c "echo -n \"\${PWD} \"; ls -t *.tar.* | head -n 1" \; | sort -u -k1,1 | tr ' ' / | xargs -n 1 tar tvf
substituirá o espaço que separa o caminho do nome do arquivo por “/”, e passará o resultado para xargs
o qual será executado tar tvf
em cada arquivo.
Para solicitar entre cada tarball, adicione -p
ao xargs
comando:
find . -name \*.tar.\* -execdir sh -c "echo -n \"\${PWD} \"; ls -t *.tar.* | head -n 1" \; | sort -u -k1,1 | tr ' ' / | xargs -p -n 1 tar tvf
Responder2
Com zsh
, no estilo típico somente de gravação:
for dir (*/*(N/)) (){(($#)) && tar tvf $1} $dir/*.tar.gz(Nom[1])
for var (values) cmd
: forma mais curta defor var in values; do cmd; done
(N/)
,(Nom[1])
: qualificadores globaisN
: expande para nada se não houver correspondência (nullglob)/
: apenas diretóriosom
: ordenar por hora de modificação (mais recente primeiro)[1]
: apenas primeira partida
(){...} args
: funções anônimas com seus argumentos.
Com as ferramentas GNU (ainda sem fazer nenhuma suposição sobre quais bytes os nomes dos arquivos podem conter, mas atravessando diretórios ocultos e incluindo tar.gz
arquivos ocultos) e qualquer shell do tipo Bourne, o equivalente poderia ser:
LC_ALL=C find . -mindepth 3 -maxdepth 3 -name '*.tar.gz' -printf '%T@:%p\0' |
sort -zn | LC_ALL=C awk -v RS='\0' -v ORS='\0' '
{match($0, ":((.*)/.*)", parts); newest[parts[2]] = parts[1]}
END {for (dir in newest) print newest[dir]}' |
xargs -r0n1 tar tvf