maxim-ka
Goto Top

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.):

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)."

Content-Key: 581196

Url: https://administrator.de/contentid/581196

Printed on: April 26, 2024 at 03:04 o'clock

Member: Fennek11
Fennek11 Jun 21, 2020 at 14:53:41 (UTC)
Goto Top
Für eine Datei geht:

$Pfad = 'C:\Users\xxx\Desktop\'  # <<< anpassen >>>  
$file = 'test.txt'  

$data = get-content ($Pfad + $file) -TotalCount 300

$pos = $data[9].LastIndexOf('/')  
$Nm = $data[9].Substring($pos+1)
$Nm = $Nm.Replace('"', '')  

rename-item ($Pfad + $file) ($Pfad + $Nm)
Member: Maxim-Ka
Maxim-Ka Jun 21, 2020 updated at 15:08:39 (UTC)
Goto Top
Danke! Aber wie geht es für mehrere Dateien? Und ich habe ganz vergessen: ich brauche eine Lösung für Linux-Shell.
Member: ziqz00ma
ziqz00ma Jun 21, 2020 updated at 16:58:52 (UTC)
Goto Top
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'  
Member: HanTrio
HanTrio Jun 21, 2020 at 17:08:03 (UTC)
Goto Top
Sowas hier sollte eigentlich funktionieren. Nicht perfekt, aber mal als Ansatz:

#!/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".
Member: colinardo
colinardo Jun 22, 2020, updated at Jun 23, 2020 at 07:27:13 (UTC)
Goto Top
Servus
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
Grüße Uwe
Mitglied: 93578
93578 Jun 23, 2020 at 07:54:10 (UTC)
Goto Top
Der Genosse ist wohl weg vom Fenster... Aber Script von colinardo ist echt nutzlich für eine bestimmte "Zielgruppe". Deswegen sage ich hier: "Danke!"