TL; DR:
Todos los archivos que están presentes en ambos src
y dest
se pueden eliminar de dest
esta manera:
find . -maxdepth 1 -type f -exec cmp -s '{}' "$destdir/{}" \; -exec mv -n "$destdir/{}" "$toDelete"/ \;
Para una explicación paso a paso, ver más abajo.
Simplificando el problema:
Para comprender qué hizo realmente el comando que queremos deshacer, comenzamos por simplificarlo:
El comando que queremos deshacer es
sudo cp From_SOURCE/* To_DESTINATION/
Para entender cómo deshacer, sudo
no es relevante.
Usaré los nombres de directorio src
para From_SOURCE
y dest
para To_DESTINATION
.
Ahora, nuestro comando es:
cp src/* dest/
Si src
contiene los archivos f1
, f2
y f3
, y los directorios d1
y d2
, el shell expande ese comando para:
cp src/f1 src/f2 src/f3 src/d1 src/d2 dest/
Sin opciones como -r
, -R
o -a
, el comando cp
no copia directorios.
Eso significa que el comando los dejará fuera, mostrando un error para cada uno de ellos:
$ cp src/f1 src/f2 src/f3 src/d1 src/d2 dest/
cp: omitting directory 'src/d1'
cp: omitting directory 'src/d2'
Eso significa que solo hemos copiado archivos simples, y no directorios, a dest
.
Decidir qué archivos eliminar:
Posiblemente había archivos con dest
el mismo nombre que los archivos src
. En este caso, los archivos se sobrescribieron (1). Es demasiado tarde para ellos, lo siento. Recuperarlos de la última copia de seguridad.
Con respecto a los archivos que están allí, queremos eliminar solo los archivos que se han copiado. Estos archivos existen en ambos directorios, con el mismo nombre y el mismo contenido.
Entonces buscamos estos archivos:
En primer lugar, cd
en src
, porque hace que los siguientes find
comandos mucho más simples, y establecer una variable en la ruta absoluta del dest:
$ cd src
$ destdir="$(readlink -f dest)"
Luego, enumeramos todos los archivos en src:
$ find . -maxdepth 1 -type f
y, para cada archivo encontrado, use cmp
para verificar si hay un archivo con el mismo contenido en dest:
$ find . -maxdepth 1 -type f -exec cmp -s '{}' "$destdir/{}" \; -print
Eliminando los archivos, cuidadosamente:
Estos archivos son los que queremos eliminar. Pero para estar seguros, primero los movemos a un directorio diferente, y echamos un vistazo a los comandos antes de ejecutarlos:
$ 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/`
¡Se ve bien! Ahora podemos dejar echo
de ejecutar los mv
comandos reales :
find . -maxdepth 1 -type f -exec cmp -s '{}' "$destdir/{}" \; -exec mv -n "$destdir/{}" "$toDelete"/ \;
Todos los archivos desde dest
que fueron copiados de src
, y todavía en realidad la misma en src
y dest
, ahora están en /tmp/toDelete/
, y pueden ser removidos después de tomar una última mirada.
Notas:
(1) Verifique si cp
es un alias cp -i
o no, eso habría evitado sobrescribir archivos preguntando primero.