Tengo esta situación en la que hay muchos archivos con nombres similares (pero todos siguen un patrón) en diferentes subcarpetas.
file1
file1 (Copy)
/folder1/file2.txt
/folder1/file2 (Copy).txt
/folder1/file3.png
/folder1/file3 (Copy).png
Cada archivo está en la misma carpeta de su copia y tiene la misma extensión, la diferencia es que tiene (Copy)
al final del nombre
Quiero obtener todos estos archivos y eliminar el más antiguo, luego eventualmente cambiar el nombre del archivo, por ejemplo, file1 (Copy)
a file1
(es decir, eliminar el (Copy)
sufijo) si es necesario cambiarle el nombre.
Estaba pensando en usar find
y mv
pero no estoy seguro de cómo decirle que mueva el más reciente.
Respuesta1
Extendidofind
+bash
solución (también necesita la implementación GNU de stat
):
find . -type f -name "* (Copy).*" -exec bash -c 'p="${0%/*}"; bn="${0##*/}";
main_bn="${bn/ (Copy)/}";
if [ -f "$p/$main_bn" ]; then
t_copy_file=$(stat -c %Y "$0"); t_main_file=$(stat -c %Y "$p/$main_bn");
if [[ $t_copy_file -gt $t_main_file ]]; then
mv "$0" "$p/$main_bn";
else
rm "$0";
fi;
fi' {} \;
p="${0%/*}"
- ruta de archivo/ruta con nombre base recortadobn="${0##*/}"
- nombre base del archivomain_bn="${bn/ (Copy)/}"
- eliminar(Copy)
la subcadena del nombre base para obtener elprincipal/comúnnombre baseif [ -f "$p/$main_bn" ]
- Si elprincipal/originalEl archivo existe (y se descubre que es un archivo normal después de la resolución del enlace simbólico).t_copy_file=$(stat -c %Y "$0")
- obtener la hora de la última modificación encontrada"Copiar"archivot_main_file=$(stat -c %Y "$p/$main_bn")
- obtener la hora de la última modificación deoriginalarchivoif [[ $t_copy_file -gt $t_main_file ]]
- Si el"Copiar"El archivo es el más reciente: muévalo aloriginaluno (hazlooriginal) conmv "$0" "$p/$main_bn"
- de lo contrario - eloriginalel archivo es el reciente, eliminando "Copiar"archivo con
rm "$0"
O un poco más corto con -nt
el operador de prueba de archivos ( [ newerfile –nt olderfile ]
verifique si newerfile
se cambió más recientemente que olderfile
, o si newerfile
existe y olderfile
no):
find . -type f -name "* (Copy).*" -exec bash -c 'p="${0%/*}"; bn="${0##*/}";
main_bn="${bn/ (Copy)/}";
if [ -f "$p/$main_bn" ]; then
if [ "$0" -nt "$p/$main_bn" ]; then
mv "$0" "$p/$main_bn";
else
rm "$0";
fi;
fi' {} \;
Respuesta2
Puede ser más fácil con zsh
:
setopt extendedglob # best in ~/.zshrc
for file (./**/?*" (Copy)"*(ND.)) {
base=$file:h/${${file:t}/" (Copy)"}}
[[ ! -f $base || -L $base ]] ||
if [ $file -nt $base ]; then
mv $file $base
else
rm -f $file
fi
}
Es posible que desees comprobar primero que no haya file (Copy) (Copy).txt
archivos.
**/
: cualquier nivel de subdirectorioN
:globo nuloexpandirse a nada si no hay ninguna coincidencia en lugar de generar un errorD
: incluye archivos ocultos (D
archivos ot) y desciende a directorios ocultos..
: solo incluyeregulararchivos (sin directorio, quince, dispositivo, enlace simbólico...)$file:h
:cabezadel archivo (parte del directorio), como encsh
$file:t
:cola(parte del nombre de archivo)${var/pattern/replacement}
, aquí sin reemplazo[[ ! -f $base || -L $base ]] ||...
omita archivos o enlaces simbólicos no normales (incluso si apuntan a archivos normales) como medida de seguridad.[ $file -nt $base ]
: devuelve verdadero si$file
se modificó por última vezdespués$base
(o$base
no es accesible, no deberíamos pasar siguiendo la verificación anterior).