• Willkommen im Linux Club - dem deutschsprachigen Supportforum für GNU/Linux. Registriere dich kostenlos, um alle Inhalte zu sehen und Fragen zu stellen.

Dateiendungen hinzufügen, die zweite.

MrLight

Newbie
Hallo Linux Forum.

Da mir irgend jemand mal erzählt hat, dass man keine alten Themen aus dem Grab heben sollte, mache ich einfach ein neues Thema auf, welches genau da anschließen sollte, wo dieses (Dateiendungen hinzufügen) endete.

Ich habe ein vergleichbares Problem. Einen Linuxserver wo sich ein Ordner mit Unterordnern befindet, wo, neben anderen Dateien, auch viele Bilder sind ohne Dateiendung. Die anderen Dateien interessieren mich nicht, diese sollen unverändert bleiben, wie auch Bilder die eine (richtige) Endung haben.

Dafür würde ich gerne das kleine Script aus dem anderen Thred benutzen:

Code:
    #!/usr/bin/env python
    #-*- coding: iso-8859-1 -*-

    import os

    DIR = os.getcwd()

    filenames = os.listdir(DIR)

    for i in filenames:

        CH = os.popen("file " + i)
        ftype = CH.read().rstrip("\n")

        if "JPEG" in ftype and not i.endswith(".jpg"):
            os.rename(DIR + "/" + i, DIR + "/" + i + ".jpg")
            print "Renamed:\t" + i + "\t" + i + ".jpg"

Nur würde ich ungerne für jeden Dateityp ein separates Script schreiben, und frage daher, ob es möglich ist ein ELSEIF oder ELSE IF einzubauen, und wie das aussehen würde. oder noch schöner einen SWITCH...

Als Beispiel habe ich eps Dateien aus Photoshop, file gibt da aus:
Code:
PostScript document text conforming DSC level 3.0, type EPS

Für ein paar Tips, bei meinem Scripting Unwissen, währe ich dankbar.

LG
 

framp

Moderator
Teammitglied
Habe das Script mal mit ein paar Ausgaben versehen und eine Map fuer Typ und Extension eingefügt. Damit solltest Du weiterkommen.
Code:
#!/usr/bin/env python
# -*- coding: iso-8859-1 -*-

import os

DIR = os.getcwd()

type2extMap = [
               ["JPEG",".jpg"], 
               ["EPS", ".eps"]
               ]

filenames = os.listdir(DIR)

for i in filenames:

    CH = os.popen("file " + i)
    ftype = CH.read().rstrip("\n")
    print "Found file %s with type %s" % (i,ftype)

    for (fileType, extension) in type2extMap:

        if fileType in ftype and not i.endswith(extension):
#            os.rename(DIR + "/" + i, DIR + "/" + i + extension)
            print "Renamed:\t" + i + "\t" + i + extension
 
A

Anonymous

Gast
hier mal eine bash Fassung mit dem Versuch mittels "find" und "file" Kommando 21 Bildtypen zu finden und mittels "mv" zu benennen. Aber alle exotischen und möglichen Containerformate die ebenfalls Bilder enthalten könnten sind so auch nicht zu erreichen. Problem hierbei zB bei einigen "JPEG 2000" Formaten.
Script MUSS UNTER BASH LAUFEN. nicht alle anderen teilweise zur bash kompatiblen Shells unterstützen hier alles was im Script verwendet wurde.
Die Zeile die die Dateien umbenennen würde ist im Moment noch auskommentiert. Erst mal die Ausgaben anschauen bevor das Script scharf gemacht wird.

Code:
#!/bin/bash 

MIMETYPEN="gif jp2 jpeg png svg+xml tiff vnd.adobe.photoshop vnd.djvu x-coreldraw x-cpi x-ico x-ms-bmp x-niff x-portable-bitmap x-portable-greymap x-portable-pixmap x-quicktime x-xcursor x-xpmi x-tga x-xcf"

EXTENSION="gif jp2 jpeg png svg tif psd djvu cdr cpi ico bmp niff pbm pgm ppm qtif cur xpm tga xcf"

readarray -t MIME < <(echo $MIMETYPEN | tr -s  " " "\n")
readarray -t EXT < <(echo $EXTENSION | tr -s " " "\n")

while read FILE
do
        TYPE=$(file -i "$FILE"  | sed -n 's/^.*:.*image\/\(.*\);.*$/\1/p')
        if [ $TYPE ]
        then
                for ((i=0;i<${#MIME[@]};i++))
                do
                        if [ ${TYPE} = ${MIME[$i]} ]
                        then
                                echo "mv $FILE ${FILE}.${EXT[$i]}"

#die nächste Zeilen auskonfigurieren dann ist das Script scharf
#                               mv -i "$FILE" "${FILE}.${EXT[$i]}"

                                break
                        fi
                done
        else
                echo Fehler: keine eindeutiges MIME-Bildformat gefunden:  $(file $FILE)
        fi
done < <(find . -type f  ! -name "*.*")

wenn eure file Version mehr MIME-Bildtypen sauber erkennt, ist das Script oben unbegrenzt erweiterbar.

Änderung : letzte Scriptzeile wurde geändert.

robi
 
OP
M

MrLight

Newbie
Also erst mal Danke an euch beide.

Das erste Script scheint es zu machen, geht aber nicht rekursiv ab da wo ich bin in alle Unterordner, und da sind viele.

Das zweite Script Spuckt andauernd solche Fehler wie dieses:

Fehler: keine eindeutiges MIME-Bildformat gefunden: ./mauritius_000001_highres.jpg: JPEG image data, JFIF standard 1.02

Das ist doch ein JPG Bild, oder verstehe ich das falsch?

LG
 
OP
M

MrLight

Newbie
Noch eine kleine Anmerkung zum zweiten Script,

ich bekomme am Anfang noch die Meldung:

../convimages2.sh: line 8: readarray: command not found
../convimages2.sh: line 9: readarray: command not found

obwohl ich das Script wie folgt aufrufe:

bash ../convimages2.sh

Um ein paar Hinweise währe ich wirklich dankbar, denn ich hänge im Moment wirklich ein wenig.

Danke & LG
 
OP
M

MrLight

Newbie
Hier noch eine Info zum bash auf diesem System:

[root@server]# bash --version
GNU bash, version 3.2.9(1)-release (x86_64-redhat-linux-gnu)
Copyright (C) 2005 Free Software Foundation, Inc.
 
OP
M

MrLight

Newbie
Und noch eine Kleinigkeit zu Script 2:

Dieses scheint ein Problem mit Leerzeichen im Namen zu haben.
 
A

Anonymous

Gast
MrLight schrieb:
Und noch eine Kleinigkeit zu Script 2:

Dieses scheint ein Problem mit Leerzeichen im Namen zu haben.

Es ist ein Fehler in der letzten Zeile, das -print ist nicht die letzte Option, , ist nätürlich Schwachsinn.
das -print am besten dort ganz aus der Zeile rausnehmen ( habe ich mal geändert)

Ansonsten habe ich jetzt getestet
bash --version
GNU bash, version 4.1.10(1)-release (i586-suse-linux-gnu)
Copyright (C) 2009 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
und
GNU bash, Version 4.2.24(1)-release (i586-suse-linux-gnu)
und das ist schon wirklich keine neuen Version. Was hast du dort für ein Linux am laufen ?
Wann genau "readarray" in die Bash gekommen ist, keine Ahnung aber bestimmt nicht vom Anfangbegin der Zeit

Ohne diesen Befehl müsste man das Script komplett umschreiben, bzw die beiden readarray Zeilen durch zB. folgendes ersetzen
Code:
typeset -i j=0
for k in $MIMETYPEN
do
        MIME[$j]=$k
        j=j+1
done
j=0
for k in $EXTENSION
do
        EXT[$j]=$k
        j=j+1
done
na ich hoffe deine Bash kennt wenigstens schon Arrays ;)

Ein Leerzeichenproblem habe ich nach der Änderung der find-Zeile auf die Schnelle nicht feststellen können. Wohl aber ist dieses Script nicht 100% sicher gegen alle möglichen und unmöglichen Sonderzeichen in Dateinamen oder Path (reagiert zB nicht wenn dort ein Punkt drin ist, bzw macht Probleme wenn ein Doppelpunkt im Dateinamen ist, und Schlimmstenfalls wenn Doppelpunkt und auch "image" im Dateinamen vorkommt), ließe sich aber alles mit einigem Aufwand fast 100,0%ig einrichten.

Wird nur bei dir nicht viel Sinn machen, denn da ist noch ein weiterer Befehl mit im Spiel. der muss bei
"file -i dateiname" auch wirklich die MIME-Typen sauber anzeigen.
und zwar in genau der Version wie sie hier im Script verarbeitet wird
Code:
# file -i *
t0092864.jpg:         image/jpeg; charset=binary
t0099328.jpg:         image/jpeg; charset=binary
test.awk:             text/x-awk; charset=utf-8
UID-Datei:            text/plain; charset=us-ascii
umsetzung.sh:         text/x-shellscript; charset=utf-8
version (1.0) string: inode/x-empty; charset=binary
image/jpeg; genau das jpeg hier hinter dem "image/" und vor dem ";" wird hier im Script ausgewertet. Möglich und wahrscheinlich deine "file" Version ist da auch noch recht alt.
Musst du einfach mal schauen was "file -i *" bei dir für Ergebnisse bei den JPEGs anzeigt, und eventuell die MIMETYPEN= Zeile entsprechend anpassen. Aber Reihenfolge nicht durcheinanderbringen.

Beim Entwickeln des Scriptes hatte ich die
file -v
file-5.11
magic file from /etc/magic:/usr/share/misc/magic
und auch diese Version ist nicht sonderlich aktuell.
Bei dem "find" Befehl hat sich in den letzten Jahren sehr viel in der Datenbasis im innerem Befehlablauf getan und es gibt ständig Änderungen, sowie verwenden einige Distributionen zu allem Unnutz auch noch eigene mehr oder weniger modifizierte Magic-files als Datenbasis, so kann es durchaus vorkommen, dass da alte Versionen ganz andere Ausgaben machen, und die Ausgaben dieses Befehls zwischen einem sehr altem Linux nicht genauso aussieht, wie auf einer einigermaßen aktuellen Maschine.
Das macht die Verwendung dieses Befehls im Script nicht gerade sonderlich rückwärts kompatibel.

robi
 

abgdf

Guru
robi schrieb:
MrLight schrieb:
Und noch eine Kleinigkeit zu Script 2:

Dieses scheint ein Problem mit Leerzeichen im Namen zu haben.

Es ist ein Fehler in der letzten Zeile, das -print ist nicht die letzte Option, , ist nätürlich Schwachsinn.
das -print am besten dort ganz aus der Zeile rausnehmen ( habe ich mal geändert)
Manchmal ist bash mit dem Umgang mit Leerzeichen (und anderen Eigenheiten wie unerwarteten Subshells) eben einfach nur Krampf.
Man mag es mit viel Mühe hinbekommen, aber in Skriptsprachen ist es dann viel schneller und einfacher geschrieben.

Rekursiv ginge in Python mit "os.path.walk()", aber ich hab' da grad' keinen Bock drauf. ;)
 

framp

Moderator
Teammitglied
abgdf schrieb:
...Rekursiv ginge in Python mit "os.path.walk()", aber ich hab' da grad' keinen Bock drauf. ;)
Oder man nutzt die Fähigkeiten von Linux und traversiert rekursiv alle Verzeichnisse mit 'find' und führt in diesen das Python Script aus :)
 

Faxxon

Member
robi schrieb:
Ohne diesen Befehl müsste man das Script komplett umschreiben, bzw die beiden readarray Zeilen durch zB. folgendes ersetzen
Code:
typeset -i j=0
for k in $MIMETYPEN
do
        MIME[$j]=$k
        j=j+1
done
j=0
for k in $EXTENSION
do
        EXT[$j]=$k
        j=j+1
done

Aus welchem Grund definierst Du das Array nicht einfach?
Code:
MIME=($MIMETYPEN)

oder besser gleich:
Code:
MIME=(gif jp2 jpeg png svg+xml tiff vnd.adobe.photoshop vnd.djvu x-coreldraw x-cpi x-ico x-ms-bmp x-niff x-portable-bitmap x-portable-greymap x-portable-pixmap x-quicktime x-xcursor x-xpmi x-tga x-xcf)
 
A

Anonymous

Gast
Faxxon schrieb:
Aus welchem Grund definierst Du das Array nicht einfach?
Code:
MIME=($MIMETYPEN)
[Ausrede]War wohl zu einfach, dass es mir gar nicht eingefallen ist. ;) [/Ausrede]

ist aber auch dem geschuldet, das ich da eigentlich etwas komplizierteres ausprobieren wollte und zwar über ein einzelnes Associatives Array, bin dort aber am Anfang über eine seltsame Fehlermeldung gestolpert bei den Mimetypen die einen Punkt haben kam immer unerklärlicherweise
"Zeile 10: vnd.adobe.photoshop: Syntaxfehler: Ungültiger arithmetischer Operator. (Fehlerverursachendes Zeichen ist \".adobe.photoshop\")."

aber mittlerweile läuft auch das.
Code:
#!/bin/bash 

MIMETYPE="gif jp2 jpeg png svg+xml tiff vnd.adobe.photoshop vnd.djvu x-coreldraw x-cpi x-ico x-ms-bmp x-niff x-portable-bitmap x-portable-greymap x-portable-pixmap x-quicktime x-xcursor x-xpmi x-tga x-xcf"

EXTENSION="gif jp2 jpeg png svg tif psd djvu cdr cpi ico bmp niff pbm pgm ppm qtif cur xpm tga xcf"

typeset -A MIME
for i in $MIMETYPE
do
        read MIME[$i]
done < <(echo $EXTENSION | tr -s " " "\n")

while read FILE
do
        TYPE=$(file -bi "$FILE"  | sed -n 's/^image\/\(.*\);.*$/\1/p')
        if [ $TYPE ]
        then
                for i in ${!MIME[@]}
                do
                        if [ ${TYPE} = $i ]
                        then
                                echo "mv $FILE ${FILE}.${MIME[$i]}"

#die nächste Zeilen auskonfigurieren dann ist das Script scharf
#                               mv -i "$FILE" "${FILE}.${MIME[$i]}"

                                break
                        fi
                done
        else
                echo Fehler: keine eindeutiges MIME-Bildformat gefunden:  $(file $FILE)
        fi
done < <(find . -type f  ! -name "*.*")

robi
 

framp

Moderator
Teammitglied
Falls Du noch an einer Pythonlösung, die Verzeichnisse rekursiv bearbeitet, interessiert bist (Finde ich persönlich etwas leichter les- und änderbar als die bash Lösung):
Code:
#!/usr/bin/env python
# -*- coding: iso-8859-1 -*-

import os

def fileTraverser(directory,topDown=True):
    for root, dirs, files in os.walk(directory):
        dirs                    # just to suppress variable not used message
        for fileName in files:
            nextFile=os.path.join(root, fileName)
            yield nextFile

MIMETYPE= "gif jp2 jpeg png svg+xml tiff vnd.adobe.photoshop vnd.djvu x-coreldraw x-cpi x-ico x-ms-bmp x-niff x-portable-bitmap x-portable-greymap x-portable-pixmap x-quicktime x-xcursor x-xpmi x-tga x-xcf" .split(" ")
EXTENSION="gif jp2 jpeg png svg     tif  psd                 djvu     cdr         cpi   ico   bmp      niff   pbm               pgm                ppm               qtif        cur       xpm    tga   xcf"   .split(" ")

type2extMap = []
for i in range(0,len(MIMETYPE)):
    type2extMap.append([MIMETYPE[i],EXTENSION[i]])
            
for fileName in fileTraverser("."):

    CH = os.popen("file '" + fileName + "'")
    ftype = CH.read().rstrip("\n")
    print "Found file %s - '%s'" % (fileName, ftype)

    for (fileType, extension) in type2extMap:
        if fileType in ftype.lower() and not fileName.lower().endswith(extension):
#            os.rename(DIR + "/" + i, DIR + "/" + fileName + "." + extension)
            print "Renamed: " + fileName + " to " + fileName + "." + extension
 
Oben