So benennen Sie Sicherungsdateien um, indem Sie die Sicherungsversion als Suffix für den Dateinamen verwenden und sie nicht mehr verbergen

So benennen Sie Sicherungsdateien um, indem Sie die Sicherungsversion als Suffix für den Dateinamen verwenden und sie nicht mehr verbergen

Ich habe mit einer großen Anzahl von Bilddateien gearbeitet. Dazu gehörte auch, alle Bilddateitypen, die über mehr als 1000 Verzeichnisse verteilt waren, direkt in ein einziges zu verschieben. Es gab viele Bilder, die genau denselben Namen hatten, aber tatsächlich unterschiedliche Bilder waren. Dazu habe ich den folgenden Einzeiler verwendet:

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

Ich habe es so gemacht, dass für alle Bilder mit demselben Namen eine versteckte Sicherungsdatei erstellt wird, anstatt sie zu überschreiben. Das hat sehr gut funktioniert, aber jetzt habe ich ein anderes Problem, das ich lösen muss.

Nun habe ich natürlich viele Kacheln, die ungefähr wie folgt aussehen:

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

Ich möchte einen Befehl (oder ein Skript) ausführen, der alle diese versteckten Dateien umbenennt, indem er die Sicherungsnummer als Suffix an den Dateinamen anfügt und .~[bu#]~ entfernt, um ihnen eindeutige und nicht versteckte Dateinamen zu geben. Also etwa so:

DSC_0616.NEF
DSC_0616_1.NEF
DSC_0616_2.NEF

Ich habe den größten Teil einiger Stunden mit Recherchen verbracht, um dies selbst zu versuchen, konnte jedoch nichts finden, das mir dabei helfen könnte und im Rahmen meines Wissensbereichs zu diesem Thema liegt.

Antwort1

Solange Sie sicher sind, dass alles wie oben beschrieben einheitlich benannt ist, können einige reguläre Ausdrücke die Aufgabe über ein Shell-Skript erledigen:

#!/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

Dies funktioniert auch beim Durchlaufen von Verzeichnissen. Platzieren Sie das Skript einfach und führen Sie es mit Ihrem Arbeitsverzeichnis oben im Verzeichnisbaum Ihres Projekts aus. Ausführen mit Beispieldateien wie den von Ihnen bereitgestellten:

###@###:~/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~

nach dem Ausführen des Skripts:

###@###:~/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

Antwort2

In den Kommentaren hat der OP nach einer Lösung gefragt, die mit allen Erweiterungen funktioniert (nicht nur .NEF), und ich hatte gerade das gleiche Problem. : p

Hier ist eine mit etwas moderneren Bashismen als die erste Antwort:

#!/usr/bin/env bash

# Renames the $1 directory's backup files (produced by `cp` or `mv` with the
# option `--backup=numbered`) such that "foo.png.~17~" becomes "foo_17.png"
function rename_backups()
{
    for THING in "${1}"/*
    do
        if [[ -f "${THING}" &&
              "${THING}" =~ ^.+\/+.+\..+~([0-9]+)~$ ]] # Take "foo.png.~17~".
        then
            # Get the "17".
            local BACKUP_NUMBER=${BASH_REMATCH[1]}

            # Remove the "~17~", leaving "foo.png".
            local SANS_BACKUP_NUMBER="${THING%.*}"

            # Get the filename, "foo", and the extension, "png".
            local FILENAME="${SANS_BACKUP_NUMBER%.*}"
            local EXT="${SANS_BACKUP_NUMBER##*.}"

            # Rename to "foo_17.png".
            local NEW_NAME="${FILENAME}_${BACKUP_NUMBER}.${EXT}"

            while [[ -f "${NEW_NAME}" ]]
            do
                # If "foo_17.png" already exists for some reason, keep
                # increasing the number until we find an unused one.
                ((++BACKUP_NUMBER))
                NEW_NAME="${FILENAME}_${BACKUP_NUMBER}.${EXT}"
            done

            mv --no-clobber "${THING}" "${NEW_NAME}"
        fi
    done
}

rename_backups your/backup/directory/here/

Die folgende Version unterstützt auchohne VerlängerungDateien:

#!/usr/bin/env bash

# Renames the $1 directory's backup files (produced by `cp` or `mv` with the
# option `--backup=numbered`) such that:
#     - "foo.png.~17~" becomes "foo_17.png"
#     - "bar.~17~" becomes "bar_17"
function rename_backups()
{
    for THING in "${1}"/*
    do
        # We'll either have a file like "foo.png.~17~" or "bar.~17~".
        if [[ -f "${THING}" && "${THING}" =~ ^.+~([0-9]+)~$ ]]
        then
            # Get the "17".
            local BACKUP_NUMBER=${BASH_REMATCH[1]}

            # Remove the "~17~", leaving, e.g., "foo.png".
            local SANS_BACKUP_NUMBER="${THING%.*}"

            # Get the filename, "foo", and the extension, "png".
            local FILENAME="${SANS_BACKUP_NUMBER%.*}"
            local EXT="${SANS_BACKUP_NUMBER##*.}"

            if [[ "${FILENAME}" == "${SANS_BACKUP_NUMBER}" ]]
            then
                # This is a "bar.~17~" case, so rename to "bar_17".
                local NEW_NAME="${FILENAME}_${BACKUP_NUMBER}"

                while [[ -f "${NEW_NAME}" ]]
                do
                    # If "bar_17" already exists for some reason, keep
                    # increasing the number until we find an unused one.
                    ((++BACKUP_NUMBER))
                    NEW_NAME="${FILENAME}_${BACKUP_NUMBER}"
                done
            else
                # This is a "foo.png.~17~" case, so rename to "foo_17.png".
                local NEW_NAME="${FILENAME}_${BACKUP_NUMBER}.${EXT}"

                while [[ -f "${NEW_NAME}" ]]
                do
                    ((++BACKUP_NUMBER))
                    NEW_NAME="${FILENAME}_${BACKUP_NUMBER}.${EXT}"
                done
            fi

            mv --no-clobber "${THING}" "${NEW_NAME}"
        fi
    done
}

rename_backups your/backup/directory/here/

verwandte Informationen