TL; DR:
Todos os arquivos que estão presentes nos dois src
e dest
podem ser removidos dest
assim:
find . -maxdepth 1 -type f -exec cmp -s '{}' "$destdir/{}" \; -exec mv -n "$destdir/{}" "$toDelete"/ \;
Para uma explicação passo a passo, veja abaixo.
Simplificando o problema:
Para entender o que o comando que queremos desfazer realmente fez, começamos por simplificá-lo:
O comando que queremos desfazer é
sudo cp From_SOURCE/* To_DESTINATION/
Para entender como desfazer, sudo
não é relevante.
Vou usar os nomes de diretório src
para From_SOURCE
e dest
para To_DESTINATION
.
Agora, nosso comando é:
cp src/* dest/
Se src
contém os arquivos f1
, f2
e f3
, e os diretórios d1
e d2
, o shell expande esse comando para:
cp src/f1 src/f2 src/f3 src/d1 src/d2 dest/
Sem opções como -r
, -R
ou -a
, o comando cp
não copia diretórios.
Isso significa que o comando os deixará de fora, mostrando um erro para cada um deles:
$ cp src/f1 src/f2 src/f3 src/d1 src/d2 dest/
cp: omitting directory 'src/d1'
cp: omitting directory 'src/d2'
Isso significa que apenas copiamos arquivos simples e nenhum diretório para dest
.
Decidindo quais arquivos remover:
Possivelmente havia arquivos com dest
o mesmo nome que arquivos src
. Nesse caso, os arquivos foram substituídos (1). É tarde demais para eles, desculpe. Recupere-os do backup mais recente.
Em relação aos arquivos existentes, queremos remover apenas os arquivos que foram copiados. Esses arquivos existem nos dois diretórios, com o mesmo nome e o mesmo conteúdo.
Então, procuramos esses arquivos:
Primeiro, cd
em src
, porque faz as seguintes find
comandos muito mais simples, e definir uma variável para o caminho absoluto do dest:
$ cd src
$ destdir="$(readlink -f dest)"
Em seguida, listamos todos os arquivos no src:
$ find . -maxdepth 1 -type f
e, para cada arquivo encontrado, use cmp
para verificar se há um arquivo com o mesmo conteúdo em dest:
$ find . -maxdepth 1 -type f -exec cmp -s '{}' "$destdir/{}" \; -print
Removendo os arquivos, com cuidado:
Esses arquivos são os que queremos remover. Mas para ter certeza, nós os movemos para um diretório diferente primeiro - e examinamos os comandos antes de executá-los:
$ toDelete=/tmp/toDelete ; mkdir -p "$toDelete"
$ find . -maxdepth 1 -type f -exec cmp -s '{}' "$destdir/{}" \; -exec echo mv -n "$destdir/{}" "$toDelete"/ \;
mv -n /path/to/dest/./f1 /tmp/toDelete/`
mv -n /path/to/dest/./f2 /tmp/toDelete/`
mv -n /path/to/dest/./f3 /tmp/toDelete/`
Parece bom! Agora podemos deixar echo
de executar os mv
comandos reais :
find . -maxdepth 1 -type f -exec cmp -s '{}' "$destdir/{}" \; -exec mv -n "$destdir/{}" "$toDelete"/ \;
Todos os arquivos dest
copiados src
e ainda os mesmos em src
e dest
agora estão em /tmp/toDelete/
e podem ser removidos depois de uma última olhada.
Notas:
(1) Verifique se cp
há um alias mais cp -i
ou menos, que teria evitado sobrescrever arquivos perguntando primeiro.