Eu só realizei testes de funcionalidade limitados, então, por favor, tenha cuidado com este comando (--dry-run):
rsync -avPr --ignore-existing --remove-source-files src/ dest
Por favor, note o trailing / como isso vai recursão em src em vez de copiar src em si, isso deve manter seus caminhos existentes.
Ao usar o sinalizador --ignore-existing em combinação com o sinalizador --remove-source-files, você excluirá apenas os arquivos de src que são sincronizados de src para dest, ou seja, arquivos que não existiam anteriormente em dest somente.
Para excluir arquivos não sincronizados, ou seja, aqueles que já existiam em dest / as em src /, você pode usar:
for file in 'find src/ -type f'; do diff $file 'echo $file | sed 's/src/dest/'' && rm $file || echo $file; done
ou
find src -type f -exec bash -c 'cmp -s "$0" "${0/#src/dest}" && rm "$0"' {} \;
se os nomes de arquivos puderem conter espaços em branco / novas linhas /… Com relação ao comentário de Gilles sobre personagens especiais, isso é certamente algo para se ter em mente e existem muitas soluções, a mais simples seria passar um -i para rm que irá avisar antes de toda deleção. Desde que src /, ou seu caminho pai, seja fornecido para localizar, no entanto, o caminho completo deve resultar em todos os nomes de arquivos sendo manipulados corretamente pelos comandos diff e rm sem aspas.