staging.inyokaproject.org

Massenänderung Dateidatum

Status: Gelöst | Ubuntu-Version: Kubuntu 22.04 (Jammy Jellyfish)
Antworten |

dietzi

Anmeldungsdatum:
21. Januar 2009

Beiträge: Zähle...

Hallo!

In einem Ordner habe ich hunderte Fotos mit dem gleichen Namensschema: YYYYMMDD_HHMMSS.jpg

Durch verschiedene Dateioperationen (Kopieren, Verschieben, Bearbeiten) stimmt das Dateidatum nicht mit diesem Namensschema überein. Dadurch gibt es z.B. die Datei "20180401_154342.jpg" mit Dateidatum "05.02.22 14:39", dem Datum der letzten Dateioperation. Ich möchte als Dateidatum analog zum Dateinamen "01.04.18 15:43:42".

Dazu lasse ich sed den Dateinamen schon in den benötigten Gruppen auslesen: YYYYMMDD_HHMMSS.jpg → [YY][YYMMDD]_[HHMM][SS].jpg

Das ist auf den ersten Blick verwirrend, weil das Dateidatum ja folgendermaßen dargestellt wird [DD].[MM].[YY] [HH]:[MM], aber zum Ändern mit touch eine andere Eingabe verlangt wird, eben in folgender Form: [YYMMDD][HHMM].[SS]

Soweit die Theorie, für eine einzelne Datei konnte ich das auch schon erfolgreich testen(leider mit beschränkten Scriptingfähigkeiten).

In einer testdatei habe ich folgenden Dateinamen notiert: 20180401_154342.jpg, lese ihn aus und speichere ihn in einer Variable

1
2
3
4
dateiname=$(cat testdatei)
# Kontrolle  
echo $dateiname  
20180401_154342.jpg

Wie oben beschrieben werden Gruppen ausgelesen und neu zusammengesetzt

1
2
3
4
dateidatum=$(sed 's/\(^[0-9]\{2\}\)\([0-9]\{6\}\)_\([0-9]\{4\}\)\([0-9]\{2\}\).jpg/\2\3\.\4/g' < testdatei )
# Kontrolle
echo $dateidatum  
1804011543.42

Damit wird das Dateidatum wie gewünscht analog zum Dateinamen geändert.

1
touch -t $dateidatum $dateiname

Aber wie am Anfang erwähnt, habe ich nicht nur eine Handvoll Dateien, sondern hunderte. Meine Programmierfähigkeiten reichen noch soweit um zu wissen daß diese Anforderung einen Loop braucht. Muß ich mit find eine Liste generieren die dann in einem Rutsch abgearbeitet wird? Kann ich im Loop für jede einzelne Datei sofort die Umbenennung anstoßen?

Da bin ich auf Input von außen angewiesen, ich bedanke mich schon mal bei jedem der sich mit meiner Anforderung beschäftigen mag.

Dietmar

user_unknown

Avatar von user_unknown

Anmeldungsdatum:
10. August 2005

Beiträge: 17630

dietzi schrieb:

Dadurch gibt es z.B. die Datei "20180401_154342.jpg" mit Dateidatum "05.02.22 14:39", dem Datum der letzten Dateioperation.

Je nach Dateisystem gibt es bei Linux 3-4 Dateidatumsdaten ☺, das Datum der Dateigeburt (gibt es meist nicht), das m-Datum der letzten Modifikation des Inhalts (das ist dominant und wird meist angezeigt bzw. davon ist meist die Rede), das a-Datum (Access), wann der Inhalt der Datei zuletzt gelesen wurde sowie das c-Datum (Change) das Änderung erfasst, wie Eigentümerübertragung. Beim Kopieren werden aber oft alle Datümse neu gesetzt. Touch arbeitet per default auch mit dem m-date, dem Zeitpunkt der letzten inhaltlichen Änderung.

Ich möchte als Dateidatum analog zum Dateinamen "01.04.18 15:43:42".

Gerade bei Photos ist das gut zu überdenken.

Wenn Du diese mit einem Windowsuser teilen willst (per E-Mail schicken, USB-Stick, DVD, ...) oder mit einem Gerät, das Windowsmedien erwartet (Fernseher mit USB-Slot oder SDCard u.ä.) scheiden Doppelpunkte aus, da diese für Laufwerksbuchstaben vorbehalten sind (genauer: Partitionsbuchstaben).

Von Leerzeichen in Dateinamen sollte man ganz generell Abstand nehmen, aber Binde- und Unterstriche sind fein.

Wie oben beschrieben werden Gruppen ausgelesen und neu zusammengesetzt

1
2
3
4
dateidatum=$(sed 's/\(^[0-9]\{2\}\)\([0-9]\{6\}\)_\([0-9]\{4\}\)\([0-9]\{2\}\).jpg/\2\3\.\4/g' < testdatei )
# Kontrolle
echo $dateidatum  
1804011543.42

Wenn Du einen Sedbefehl mit vielen Klammern und Backslashes vereinfachen willst, dann kommt Dir vielleicht der Schalter -r zu Pass:

1
2
3
4
dateidatum=$(sed -r 's/(^[0-9]{2})([0-9]{6})_([0-9]{4})([0-9]{2}).jpg/\2\3\.\4/g' < testdatei )
# Kontrolle
echo $dateidatum  
1804011543.42

Damit wird das Dateidatum wie gewünscht analog zum Dateinamen geändert.

1
touch -t $dateidatum $dateiname

Aber wie am Anfang erwähnt, habe ich nicht nur eine Handvoll Dateien, sondern hunderte. Meine Programmierfähigkeiten reichen noch soweit um zu wissen daß diese Anforderung einen Loop braucht. Muß ich mit find eine Liste generieren die dann in einem Rutsch abgearbeitet wird? Kann ich im Loop für jede einzelne Datei sofort die Umbenennung anstoßen?

Jein.

Das find ist bereits eine Loop.

Man muss nicht eine Liste generieren, sondern kann gleich für jede Datei ein Skript oder Kommando anstoßen, das die Namenskonversion anstößt.

1
find fotowurzelverz -name "*.jpg" -execdir /wo/ist/mein/datumsscript.sh {} ";" 

Da bin ich auf Input von außen angewiesen, ich bedanke mich schon mal bei jedem der sich mit meiner Anforderung beschäftigen mag.

Keine Ursache.

dietzi

(Themenstarter)

Anmeldungsdatum:
21. Januar 2009

Beiträge: 17

Hallo "Unbekannt",

danke mal für die ausführlichen Infos, ich werde sie heute oder morgen mal umzusetzen versuchen.

Sehr amüsant finde ich deine Wortkreation Datümse.

Dietmar

dietzi

(Themenstarter)

Anmeldungsdatum:
21. Januar 2009

Beiträge: 17

Grundsätzlich sollte das Script also so ausschauen:

1
2
3
4
#!/bin/sh

dateidatum=$(sed -r 's/(^[0-9]{2})([0-9]{6})_([0-9]{4})([0-9]{2}).jpg/\2\3\.\4/g' < testdatei)
touch -t $dateidatum $dateiname

Wobei das Auslesen einer Datei überflüssig ist, da ja alle gefundenen Vorkommen in "{}" gespeichert sind. Dasselbe gilt für die Variable "$dateiname". Aber durch irgendwas muß ich sie ja ersetzen, ohne funktioniert das Script überhaupt nicht. Versuchsweise habe ich das Argument "$1" eingefügt.

1
2
3
4
#!/bin/sh

dateidatum=$(sed -r 's/(^[0-9]{2})([0-9]{6})_([0-9]{4})([0-9]{2}).jpg/\2\3\.\4/g' < $1)
touch -t $dateidatum $1

Das liefert mir für die 5 Testdateien die Fehlermeldung

1
2
3
4
5
6
touch: Ungültiges Datumsformat »\377\330\377\341)\371ExifII*\b\017\016\001\002“
touch: Ungültiges Datumsformat »\377\330\377\341+\371ExifII*\b\017\016\001\002“
touch: Ungültiges Datumsformat »\377\330\377\3415\371ExifII*\b\017\016\001\002“
./datumsscript.sh: 4: touch: Argument list too long
touch: Ungültiges Datumsformat »\377\330\377\341*\371ExifII*\b\017\016\001\002“
touch: Ungültiges Datumsformat »\377\330\377\3416\371ExifII*\b\017\016\001\002“

Da stehe ich leider jetzt wieder an.

user_unknown

Avatar von user_unknown

Anmeldungsdatum:
10. August 2005

Beiträge: 17630

dietzi schrieb:

Wobei das Auslesen einer Datei überflüssig ist, da ja alle gefundenen Vorkommen in "{}" gespeichert sind. Dasselbe gilt für die Variable "$dateiname". Aber durch irgendwas muß ich sie ja ersetzen, ohne funktioniert das Script überhaupt nicht. Versuchsweise habe ich das Argument "$1" eingefügt.

Ja.

1
2
3
4
#!/bin/sh

dateidatum=$(sed -r 's/(^[0-9]{2})([0-9]{6})_([0-9]{4})([0-9]{2}).jpg/\2\3\.\4/g' < $1)
touch -t $dateidatum $1

Dem Sed übergibt man aber den Text, der transformiert werden soll, am besten so:

1
2
3
#!/bin/sh
dateidatum=$(echo $1 | sed -r 's/(^[0-9]{2})([0-9]{6})_([0-9]{4})([0-9]{2}).jpg/\2\3\.\4/g')
touch -t $dateidatum $1

dietzi

(Themenstarter)

Anmeldungsdatum:
21. Januar 2009

Beiträge: 17

Danke für diesen entscheidenden Tipp, jetzt funktioniert es wie erwartet.

touch hat sich zwar immer wieder über ein ungültiges Dateiformat beschwert:

1
touch: Ungültiges Datumsformat »./20180401_154342.jpg“

aber mit dem herauslösen von "./" war das auch erledigt. Das endgültige Script:

1
2
3
#!/bin/sh
dateidatum=$(echo $1 | sed -r 's/(^[./]{2})([0-9]{2})([0-9]{6})_([0-9]{4})([0-9]{2}).jpg/\3\4\.\5/g')
touch -t $dateidatum $1

Da hab ich wieder einiges gelernt.

Dietmar

Antworten |