Cómo cambiar el nombre de los archivos de respaldo, usando su versión de respaldo como sufijo del nombre del archivo y haciendo que ya no esté oculto

Aug 17 2020

He estado trabajando con una gran cantidad de archivos de imagen. Parte de esto fue mover todos los tipos de archivos de imagen que se distribuyeron en más de 1000 directorios en uno solo directamente. Había muchas imágenes que tenían exactamente el mismo nombre, pero de hecho eran imágenes diferentes. Usé el siguiente one-liner para hacerlo:

find . -type f -exec mv --backup=t '{}' /media/DATA-HDD/AllImages \;

Lo hice de esta manera para que cualquier imagen que tuviera el mismo nombre obtuviera un archivo de respaldo oculto, en lugar de sobrescribirlo. Funcionó muy bien, pero ahora tengo otro problema que necesito resolver.

Ahora, por supuesto, tengo muchos mosaicos que son algo así como lo siguiente:

DSC_0616.NEF
DSC_0616.NEF.~1~
DSC_0616.NEF.~2~

Lo que estoy buscando hacer es ejecutar un comando (o script), que cambiará el nombre de cualquiera de estos archivos ocultos agregando el número de respaldo como un sufijo al nombre del archivo, y eliminará el. ~ [Bu #] ~ para hacerlos únicos nombres de archivo y no ocultos. Entonces, así:

DSC_0616.NEF
DSC_0616_1.NEF
DSC_0616_2.NEF

He pasado la mayor parte de un par de horas tratando de investigar para intentar esto yo mismo, pero realmente no puedo encontrar nada que pueda ayudarme a llegar allí que esté dentro de mi ámbito de conocimiento sobre el tema.

Respuestas

1 Minty Aug 17 2020 at 09:57

Siempre que esté seguro de que todo se nombra de forma coherente como describió anteriormente, algunas expresiones regulares pueden hacer el trabajo a través de un script de shell:

#!/bin/bash
# sets the file separator to be only newlines, in case files have spaces in them
IFS=$'\n' for file in $(find . -type f); do
        # parses just the number(s) between two tildes, and only at the end of the file
        number=$(echo $file | grep -Eo "~[0-9]+~$" | sed s/'~'/''/g) # if no match found, assume this is a "base" file that does not need to be renamed if [ "$number" == "" ]; then
                continue
        fi
        # parses the file name through "NEF", then deletes ".NEF"
        filename=$(echo $file |  grep -Eio "^.+\.NEF" | sed s/'\.NEF'/''/g )
        if [ "$filename" == "" ]; then continue fi mv -v $file $(echo "$filename"_"$number.NEF") # if anything went wrong, exit immediately if [ "$?" != "0" ]; then
                echo "Unable to move file $file"
                exit 1
        fi
done

Esto también funcionará para descender a través de directorios, simplemente coloque el script y ejecútelo con su directorio de trabajo en la parte superior del árbol de directorios de su proyecto. Ejecutando con archivos de ejemplo como los que proporcionó:

###@###:~/project$ find . -type f
./DSC_0616.NEF.~8~
./DSC_0616.NEF.~5~
./DSC_0616.NEF.~1~
./DSC_0616.NEF.~7~
./DSC_0616.NEF.~3~
./DSC_0616.NEF.~4~
./DSC_0616.NEF.~9~
./DSC_0616.NEF.~2~
./DSC_0616.NEF.~6~
./lower_dir/DSC_0616.NEF.~8~
./lower_dir/DSC_0616.NEF.~5~
./lower_dir/DSC_0616.NEF.~1~
./lower_dir/DSC_0616.NEF.~7~
./lower_dir/DSC_0616.NEF.~3~
./lower_dir/DSC_0616.NEF.~4~
./lower_dir/DSC_0616.NEF.~9~
./lower_dir/DSC_0616.NEF.~2~
./lower_dir/DSC_0616.NEF.~6~

después de ejecutar el script:

###@###:~/project$ find . -type f
./DSC_0616_1.NEF
./DSC_0616_3.NEF
./DSC_0616_7.NEF
./DSC_0616_5.NEF
./DSC_0616_2.NEF
./DSC_0616_9.NEF
./DSC_0616_6.NEF
./DSC_0616_8.NEF
./DSC_0616_4.NEF
./lower_dir/DSC_0616_1.NEF
./lower_dir/DSC_0616_3.NEF
./lower_dir/DSC_0616_7.NEF
./lower_dir/DSC_0616_5.NEF
./lower_dir/DSC_0616_2.NEF
./lower_dir/DSC_0616_9.NEF
./lower_dir/DSC_0616_6.NEF
./lower_dir/DSC_0616_8.NEF
./lower_dir/DSC_0616_4.NEF