Qualquer abordagem (enumerando os arquivos usando find
ou usando um caractere curinga recursivo (**) gsutil produz uma lista de nomes de caminho para a origem da cópia, e a gsutil sempre "achatará" os caminhos quando você executá-lo deste jeito. A gsutil funciona dessa maneira porque queríamos que ela funcionasse de maneira semelhante ao antigo comando cp do Unix / Linux (que também iria achatar os caminhos quando você especificasse dessa forma, sendo todos copiados em um único diretório de destino).
Para evitar que os caminhos sejam achatados, você precisa gerar um script que forneça os caminhos completos para cada objeto:
gsutil cp pictures/bg/img.png gs://example-bucket/pictures/bg/img.png
gsutil cp pictures/pictures/dog.jpg gs://example-bucket/pictures/pictures/dog.jpg
...
Para obter o paralelismo, você pode executar cada comando em segundo plano:
gsutil cp pictures/bg/img.png gs://example-bucket/pictures/bg/img.png &
gsutil cp pictures/pictures/dog.jpg gs://example-bucket/pictures/pictures/dog.jpg &
...
wait
Se você estiver copiando um grande número de arquivos, provavelmente precisará limitar o paralelismo para evitar sobrecarregar sua máquina (faça N e espere, faça o próximo N e espere, etc.)