Lieber Besucher, herzlich willkommen bei: GentooForum.de. Falls dies Ihr erster Besuch auf dieser Seite ist, lesen Sie sich bitte die Hilfe durch. Dort wird Ihnen die Bedienung dieser Seite näher erläutert. Darüber hinaus sollten Sie sich registrieren, um alle Funktionen dieser Seite nutzen zu können. Benutzen Sie das Registrierungsformular, um sich zu registrieren oder informieren Sie sich ausführlich über den Registrierungsvorgang. Falls Sie sich bereits zu einem früheren Zeitpunkt registriert haben, können Sie sich hier anmelden.
Quellcode |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 |
#!/usr/bin/python """mp3md5: MP3 checksums stored in ID3v2 mp3md5 calculates MD5 checksums for all MP3's on the command line (either individual files, or directories which are recursively processed). Checksums are calculated by skipping the ID3v2 tag at the start of the file and any ID3v1 tag at the end (does not however know about APEv2 tags). The checksum is stored in an ID3v2 UFID (Unique File ID) frame with owner 'md5' (the ID3v2 tag is created if necessary). Usage: mp3md5.py [options] [files or directories] -h/--help Output this message and exit. -l/--license Output license terms for mp3md5 and exit. -n/--nocheck Do not check existing checksums (so no CONFIRMED or CHANGED lines will be output). Causes --update to be ignored. -r/--remove Remove checksums, outputting REMOVED lines (outputs NOCHECKSUM for files already without them). Ignores --nocheck and --update. -u/--update Instead of printing changes, update the checksum aand output UPDATED lines. Depends on the eyeD3 module (http://eyeD3.nicfit.net) Copyright 2007 G raham P oulter """ __copyright__ = "2007 G raham P oulter" __author__ = "G raham P oulter" __license__ = """This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>.""" import eyeD3 from getopt import getopt import md5 import os import struct import sys pretend = False # Whether to pretend to write tags nocheck = False # Whether to not check existing sums remove = False # Whether to remove checksums update = False # Whether to update changed checksums def log(head, body, *args): """Print a message to standard output""" print head + " "*(12-len(head)) + (body % args) def openTag(fpath): """Attempt to open ID3 tag, creating a new one if not present""" if not eyeD3.tag.isMp3File(fpath): raise ValueError("NOT AN MP3: %s" % fpath) try: audioFile = eyeD3.tag.Mp3AudioFile(fpath, eyeD3.ID3_V2) except eyeD3.tag.InvalidAudioFormatException, ex: raise ValueError("ERROR IN MP3: %s" % fpath) tag = audioFile.getTag() if tag is None: tag = eyeD3.Tag(fpath) tag.header.setVersion(eyeD3.ID3_V2_3) if not pretent: tag.update() return tag ### WARNING: REMEMBER TO UPDATE THE COPY IN MD5DIR def calculateUID(filepath): """Calculate MD5 for an MP3 excluding ID3v1 and ID3v2 tags if present. See www.id3.org for tag format specifications.""" f = open(filepath, "rb") # Detect ID3v1 tag if present finish = os.stat(filepath).st_size; f.seek(-128, 2) if f.read(3) == "TAG": finish -= 128 # ID3 at the start marks ID3v2 tag (0-2) f.seek(0) start = f.tell() if f.read(3) == "ID3": # Bytes w major/minor version (3-4) version = f.read(2) # Flags byte (5) flags = struct.unpack("B", f.read(1))[0] # Flat bit 4 means footer is present (10 bytes) footer = flags & (1<<4) # Size of tag body synchsafe integer (6-9) bs = struct.unpack("BBBB", f.read(4)) bodysize = (bs[0]<<21) + (bs[1]<<14) + (bs[2]<<7) + bs[3] # Seek to end of ID3v2 tag f.seek(bodysize, 1) if footer: f.seek(10, 1) # Start of rest of the file start = f.tell() # Calculate MD5 using stuff between tags f.seek(start) h = md5.new() h.update(f.read(finish-start)) f.close() return h.hexdigest() def readUID(fpath): """Read MD5 UID from ID3v2 tag of fpath.""" tag = openTag(fpath) for x in tag.getUniqueFileIDs(): if x.owner_id == "md5": return x.id return None def removeUID(fpath): """Remove MD5 UID from ID3v2 tag of fpath""" tag = openTag(fpath) todel = None for i, x in enumerate(tag.frames): if isinstance(x, eyeD3.frames.UniqueFileIDFrame) \ and x.owner_id == "md5": todel = i break if todel is not None: del tag.frames[i] if not pretend: tag.update(eyeD3.ID3_V2_3) return True else: return False def writeUID(fpath, uid): """Write the MD5 UID in the ID3v2 tag of fpath.""" tag = openTag(fpath) present = False for x in tag.getUniqueFileIDs(): if x.owner_id == "md5": present = True x.id = uid break if not present: tag.addUniqueFileID("md5", uid) if not pretend: tag.update(eyeD3.ID3_V2_3) def mungeUID(fpath): "Update the MD5 UID on the tag""" if remove: if removeUID(fpath): log("REMOVED", fpath) else: log("NOCHECKSUM", fpath) else: cur_uid = readUID(fpath) if cur_uid is None: new_uid = calculateUID(fpath) writeUID(fpath, new_uid) log("ADDED", fpath) elif not nocheck: new_uid = calculateUID(fpath) if cur_uid == new_uid: log("CONFIRMED", fpath) elif update: writeUID(fpath, new_uid) log("UPDATED", fpath) else: log("BROKEN", fpath) if __name__ == "__main__": optlist, args = getopt(sys.argv[1:], "hlnru", ["help","license","nocheck","remove","update"]) for key, value in optlist: if key in ("-h","--help"): print __doc__ sys.exit(0) elif key in ("-l","--license"): print license sys.exit(0) elif key in ("-n","--nocheck"): nocheck = True elif key in ("-r", "--remove"): remove = True elif key in ("-u", "--update"): update = True for start in args: if os.path.isfile(start): if start.endswith(".mp3"): mungeUID(start) elif os.path.isdir(start): for root, dirs, files in os.walk(start): dirs.sort() files.sort() for fname in files: if fname.endswith(".mp3"): mungeUID(os.path.join(root,fname)) else: log("WARNING", "%s does not exist", start) |
Quellcode |
|
1 2 3 4 |
Zeile 184 von optlist, args = getopt(sys.argv[1:], "hlnru", ["help","license","nocheck","remove","update"]) zu optlist, args = getopt(sys.argv[1:], "hlnrup", ["help","license","nocheck","remove","update","pretend"]) |
Quellcode |
|
1 2 3 |
hinter Zeile 197 eingefügt: elif key in ("-p", "--pretend"): pretend = True |
Quellcode |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
Zeile 168-181 zu: cur_uid = readUID(fpath) new_uid = calculateUID(fpath) if pretend: log($new_uid, fpath) if cur_uid is None: writeUID(fpath, new_uid) log("ADDED", fpath) elif not nocheck: if cur_uid == new_uid: log("CONFIRMED", fpath) elif update: writeUID(fpath, new_uid) log("UPDATED", fpath) else: log("BROKEN", fpath) |
Quellcode |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 |
#!/usr/bin/python """mp3md5: MP3 checksums stored in ID3v2 mp3md5 calculates MD5 checksums for all MP3's on the command line (either individual files, or directories which are recursively processed). Checksums are calculated by skipping the ID3v2 tag at the start of the file and any ID3v1 tag at the end (does not however know about APEv2 tags). The checksum is stored in an ID3v2 UFID (Unique File ID) frame with owner 'md5' (the ID3v2 tag is created if necessary). Usage: mp3md5.py [options] [files or directories] -h/--help Output this message and exit. -l/--license Output license terms for mp3md5 and exit. -n/--nocheck Do not check existing checksums (so no CONFIRMED or CHANGED lines will be output). Causes --update to be ignored. -r/--remove Remove checksums, outputting REMOVED lines (outputs NOCHECKSUM for files already without them). Ignores --nocheck and --update. -u/--update Instead of printing changes, update the checksum aand output UPDATED lines. Depends on the eyeD3 module (http://eyeD3.nicfit.net) Copyright 2007 G raham P oulter """ __copyright__ = "2007 G raham P oulter" __author__ = "G raham P oulter" __license__ = """This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>.""" import eyeD3 from getopt import getopt import md5 import os import struct import sys pretend = False # Whether to pretend to write tags nocheck = False # Whether to not check existing sums remove = False # Whether to remove checksums update = False # Whether to update changed checksums def log(head, body, *args): """Print a message to standard output""" print head + " "*(12-len(head)) + (body % args) def openTag(fpath): """Attempt to open ID3 tag, creating a new one if not present""" if not eyeD3.tag.isMp3File(fpath): raise ValueError("NOT AN MP3: %s" % fpath) try: audioFile = eyeD3.tag.Mp3AudioFile(fpath, eyeD3.ID3_V2) except eyeD3.tag.InvalidAudioFormatException, ex: raise ValueError("ERROR IN MP3: %s" % fpath) tag = audioFile.getTag() if tag is None: tag = eyeD3.Tag(fpath) tag.header.setVersion(eyeD3.ID3_V2_3) if not pretent: tag.update() return tag ### WARNING: REMEMBER TO UPDATE THE COPY IN MD5DIR def calculateUID(filepath): """Calculate MD5 for an MP3 excluding ID3v1 and ID3v2 tags if present. See www.id3.org for tag format specifications.""" f = open(filepath, "rb") # Detect ID3v1 tag if present finish = os.stat(filepath).st_size; f.seek(-128, 2) if f.read(3) == "TAG": finish -= 128 # ID3 at the start marks ID3v2 tag (0-2) f.seek(0) start = f.tell() if f.read(3) == "ID3": # Bytes w major/minor version (3-4) version = f.read(2) # Flags byte (5) flags = struct.unpack("B", f.read(1))[0] # Flat bit 4 means footer is present (10 bytes) footer = flags & (1<<4) # Size of tag body synchsafe integer (6-9) bs = struct.unpack("BBBB", f.read(4)) bodysize = (bs[0]<<21) + (bs[1]<<14) + (bs[2]<<7) + bs[3] # Seek to end of ID3v2 tag f.seek(bodysize, 1) if footer: f.seek(10, 1) # Start of rest of the file start = f.tell() # Calculate MD5 using stuff between tags f.seek(start) h = md5.new() h.update(f.read(finish-start)) f.close() return h.hexdigest() def readUID(fpath): """Read MD5 UID from ID3v2 tag of fpath.""" tag = openTag(fpath) for x in tag.getUniqueFileIDs(): if x.owner_id == "md5": return x.id return None def removeUID(fpath): """Remove MD5 UID from ID3v2 tag of fpath""" tag = openTag(fpath) todel = None for i, x in enumerate(tag.frames): if isinstance(x, eyeD3.frames.UniqueFileIDFrame) \ and x.owner_id == "md5": todel = i break if todel is not None: del tag.frames[i] if not pretend: tag.update(eyeD3.ID3_V2_3) return True else: return False def writeUID(fpath, uid): """Write the MD5 UID in the ID3v2 tag of fpath.""" tag = openTag(fpath) present = False for x in tag.getUniqueFileIDs(): if x.owner_id == "md5": present = True x.id = uid break if not present: tag.addUniqueFileID("md5", uid) if not pretend: tag.update(eyeD3.ID3_V2_3) def mungeUID(fpath): "Update the MD5 UID on the tag""" if remove: if removeUID(fpath): log("REMOVED", fpath) else: log("NOCHECKSUM", fpath) else: cur_uid = readUID(fpath) new_uid = calculateUID(fpath) if pretend: log($new_uid, fpath) if cur_uid is None: writeUID(fpath, new_uid) log("ADDED", fpath) elif not nocheck: if cur_uid == new_uid: log("CONFIRMED", fpath) elif update: writeUID(fpath, new_uid) log("UPDATED", fpath) else: log("BROKEN", fpath) if __name__ == "__main__": optlist, args = getopt(sys.argv[1:], "hlnru", ["help","license","nocheck","remove","update","pretend"]) for key, value in optlist: if key in ("-h","--help"): print __doc__ sys.exit(0) elif key in ("-l","--license"): print license sys.exit(0) elif key in ("-n","--nocheck"): nocheck = True elif key in ("-r", "--remove"): remove = True elif key in ("-u", "--update"): update = True elif key in ("-p", "--pretend"): pretend = True for start in args: if os.path.isfile(start): if start.endswith(".mp3"): mungeUID(start) elif os.path.isdir(start): for root, dirs, files in os.walk(start): dirs.sort() files.sort() for fname in files: if fname.endswith(".mp3"): mungeUID(os.path.join(root,fname)) else: log("WARNING", "%s does not exist", start) |
Quellcode |
|
1 2 3 4 5 |
$ python mp3md5.py mytestfile.mp3 File "mp3md5.py", line 170 if pretend: ^ IndentationError: unexpected indent |
Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von »H2« (16.11.2008, 19:52)
Quellcode |
|
1 2 3 4 5 |
$ python mp3md5.py mytestfile.mp3 File "mp3md5.py", line 76 raise ValueError("NOT AN MP3: %s" % fpath) ^ IndentationError: expected an indented block |
Zitat
__license__ = """This program is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as published by the
Free Software Foundation, either version 3 of the License, or (at your option)
any later version.
Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von »schade« (16.11.2008, 19:29)
Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von »H2« (16.11.2008, 20:05)
Quellcode |
|
1 2 3 |
python mp3md5.py --pretend mytestfile.mp3 b4f2d5d1a1eb2253869724ee652ccea4mytestfile.mp3 CONFIRMED mytestfile.mp3 |
Quellcode |
|
1 |
print head + " "*(80-len(head)-len(body)) + body |
Quellcode |
|
1 |
print head + " " + (body % args) |
Die Checksumme und der Dateiname wird mit dem Aufruf "log(new_uid, fpath)" ausgegeben. "new_uid" enthält die berechnete Checksumme und "fpath" den Dateinamen.Was genau von der Formatierung ist nun der filename selbst?
Ein wenig muss ich mir das skript noch ansehen, weil es ein problem mit dateien gibt die noch kein ID3 Tag haben.