Mehrere Dateien im Linux-Shell umbenennen. Dateinamen befinden sich in einer Zeile innerhalb von diesen Dateien
Hallo geehrte Gemeinde,
auf einem kurzem Trip von der Windows- Welt in die Linux-Welt habe ich auf ein Problem gestoßen.
Ich habe in einem Verzeichnis mehrere mit einem Linux-Script erzeugten Dateien OHNE Dateierweiterungen (eigentlich sind das txt-Dateien). Einige Dateien hat Script schon automatisch gelöscht, so das am Ende nur die relevanten Dateien geblieben sind (ca. 8000)
data_1
data_7
data_12
data_16
data_19
data_20
data_22
data_7997
data_7999
data_8000
In jeder von übrig gebliebenen Dateien befindet sich in der Zeile 9 ihre richtige Dateiname (z.B.):
Jede Datei hat eine eigene ungleiche Dateiname, also 8000 diversen Dateinamen.
Wie kann ich die ursprungliche Dateinamen in die richtige Dateinamen mit entsprechenden Dateityp (immer *.txt) umbenennen? So dass es am Ende so aussieht:
19_project_2513/a23.txt
19_project2503-11.txt
18_project4578_a1379.txt
oder:
Content-Description: 19_project_2513/a23.txt
Content-Description: 19_project2503-11.txt
Content-Description: 18_project4578_a1379.txt
Für jede Hilfe werde ich sehr dankbar!
Ich habe bis jetzt so was gefunden, leider klappte es nicht:
Linux schreibt immer:
"Substitution replacement not terminated at (user-supplied code)."
auf einem kurzem Trip von der Windows- Welt in die Linux-Welt habe ich auf ein Problem gestoßen.
Ich habe in einem Verzeichnis mehrere mit einem Linux-Script erzeugten Dateien OHNE Dateierweiterungen (eigentlich sind das txt-Dateien). Einige Dateien hat Script schon automatisch gelöscht, so das am Ende nur die relevanten Dateien geblieben sind (ca. 8000)
data_1
data_7
data_12
data_16
data_19
data_20
data_22
data_7997
data_7999
data_8000
In jeder von übrig gebliebenen Dateien befindet sich in der Zeile 9 ihre richtige Dateiname (z.B.):
HTTP/1.1 200 OK
Date: Sun, 21 Jun 2012 11:55:54 GMT
Server: Apache/2.4.29 (Ubuntu)
Referrer-Policy: strict-origin
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate
Pragma: no-cache
Accept-Ranges: bytes
Content-Description: 19_project_2513/a23.txt
Content-Disposition: attachment; filename="19_project_2513/a23.txt"
Jede Datei hat eine eigene ungleiche Dateiname, also 8000 diversen Dateinamen.
Wie kann ich die ursprungliche Dateinamen in die richtige Dateinamen mit entsprechenden Dateityp (immer *.txt) umbenennen? So dass es am Ende so aussieht:
19_project_2513/a23.txt
19_project2503-11.txt
18_project4578_a1379.txt
oder:
Content-Description: 19_project_2513/a23.txt
Content-Description: 19_project2503-11.txt
Content-Description: 18_project4578_a1379.txt
Für jede Hilfe werde ich sehr dankbar!
Ich habe bis jetzt so was gefunden, leider klappte es nicht:
for file in *.*; do
text="$(grep -m 1 "Content-Description:" "$file")"
rename "s?$text?" "$file"
done
Linux schreibt immer:
"Substitution replacement not terminated at (user-supplied code)."
Bitte markiere auch die Kommentare, die zur Lösung des Beitrags beigetragen haben
Content-ID: 581196
Url: https://administrator.de/contentid/581196
Ausgedruckt am: 19.11.2024 um 07:11 Uhr
6 Kommentare
Neuester Kommentar
Zitat von @Maxim-Ka:
for file in *.*; do
text="$(grep -m 1 "Content-Description:" "$file")"
rename "s?$text?" "$file"
done
Das passt schon fast. Mit "man rename" guckst du dir die Manualpage für rename an. Da siehst du:
RENAME(1) User Commands RENAME(1)
NAME
rename - rename files
SYNOPSIS
rename [options] expression replacement file...
DESCRIPTION
rename will rename (...)
In der einfachsten Variante brauchst du also drei Argumente: einen Ausdruck, einen Ersatzausdruck und einen Dateinamen
Probier's mal mit:
for file in data_*; do
new_filename="$(grep -m 1 "Content-Description:" "$file" | sed "s/Content-Description: //")";
rename --verbose --no-act "$file" "$new_filename" "$file";
done
Ich habe mir drei Testdateien nach deinem Schema angelegt. Bei mir spuckt der aus:
`data_1' -> `19_project_2513/a23.txt'
`data_2' -> `19_project_jabberwocky/b55.txt'
`data_3' -> `19_project_beta/f12.txt'
Sowas hier sollte eigentlich funktionieren. Nicht perfekt, aber mal als Ansatz:
Dabei zu beachten:
- Die Content-Description sollte kein Leerzeichen enthalten - es wird hier der letzte String der Zeile verwendet, mit dem Leerzeichen als Trenner
- Falls dort ein "/" enthalten ist (wie in deinem Beispiel), so wird ein Unterordner angelegt
-> also, es ergibt keine Datei namens "19_project_2513/a23.txt", sondern einen Unterordner namens "19_project_2513", und darin liegt dann "a23.txt".
#!/bin/bash
target_folder="/path/to/folder/" # <- entspr. anpassen
for file in $(ls $target_folder); do
new_name="$(grep -m 1 "Content-Description" $target_folder$file | awk '{print $NF}')"
[ ! -z $new_name ] && mv $target_folder$file $target_folder$new_name
done
Dabei zu beachten:
- Die Content-Description sollte kein Leerzeichen enthalten - es wird hier der letzte String der Zeile verwendet, mit dem Leerzeichen als Trenner
- Falls dort ein "/" enthalten ist (wie in deinem Beispiel), so wird ein Unterordner angelegt
-> also, es ergibt keine Datei namens "19_project_2513/a23.txt", sondern einen Unterordner namens "19_project_2513", und darin liegt dann "a23.txt".
Servus
Grüße Uwe
root="/mein/toller/ordner"
find "$root" -type f -print0 | while IFS= read -r -d '' file ;do
name=$(sed -rne 's/Content-Description:\s*(.*)/\1/p' "$file" | head -1)
folder="$root/$(dirname "$name")";filename="$(basename "$name")"
echo "Renaming '$file' => '$folder/$filename'"
mkdir "$folder" 2>/dev/null
mv "$file" "$folder/$filename"
done
Der Genosse ist wohl weg vom Fenster... Aber Script von colinardo ist echt nutzlich für eine bestimmte "Zielgruppe". Deswegen sage ich hier: "Danke!"