• Apfeltalk ändert einen Teil seiner Allgemeinen Geschäftsbedingungen (AGB), das Löschen von Useraccounts betreffend.
    Näheres könnt Ihr hier nachlesen: AGB-Änderung
  • Viele hassen ihn, manche schwören auf ihn, wir aber möchten unbedingt sehen, welche Bilder Ihr vor Eurem geistigen Auge bzw. vor der Linse Eures iPhone oder iPad sehen könnt, wenn Ihr dieses Wort hört oder lest. Macht mit und beteiligt Euch an unserem Frühjahrsputz ---> Klick

Fehler in iTunes Music Library.xml ausbügeln?

stk

Grünapfel
Registriert
05.01.04
Beiträge
7.141
Moin,

leider habe ich feststellen müssen, das in o.g. XML-File ein ziemliches Durcheinander bei einigen Pfadnamen entstanden ist. Ein erste grobe Suche findet so ca. 2500 Titel, die auf einen Speicherort verweisen, wo sie garantiert nicht liegen.

Bisher habe ich noch keine zufriedenstellende Lösung gefunden, mit der ich das wieder gerade rücken könnte. Was mir eingefallen ist:

a) die Titel identifizieren und in iTunes wieder neu verknüpfen. Zuverlässig, aber in Anbetracht der Menge sehr mühselig

b) XML-Datei in BBEdit öffnen und dort die Pfade richtig eintragen. Leider gibt es kein einheitliches Muster, nachdem die Pfade verbogen sind, so daß ich nicht umhin käme eine sehr komplexe RegEx-Regel aufzubauen. Alle meine Versuche dahingehend sind bisher jedoch eher kläglich gescheitert.

Kennt jemand evtl. ein (XML-)Tool, ein AppleScript, eine Automatoraktion, …*mit dem man sich an der Stelle weiterhelfen könnte? Der Lösungsweg könnte IMHO so aussehen:

Finde alle Musikstücke, deren Pfad nicht mit "file://Volumes/Media/iTunes%20Music/" anfängt. Ändere den Pfad auf
Code:
file://Volumes/Media/iTunes%20Music/Value%20aus%20Key%20Artist/Value%20aus%20Key%20Album/Value%20aus%20Key%20Name
.

Wie schon skizziert sollten dabei Leerschritte entsprechend umgewandelt werden, ggf. auch noch weitere Sonderzeichen/Umlaute, die man in einer Tabelle hinterlegen könnte.

Kennt wer so was schlaues?

Gruß Stefan
 

Skeeve

Pomme d'or
Registriert
26.10.05
Beiträge
3.120
Bevor ich drüber nachdenke: Bist Du sicher, daß es reicht, das auszutauschen? Die wirklichen daten holt sich iTunes doch woanders her.
Nachtrag: Ich habe mir das jetzt bei mir mal angesehen. Mit einem Perl Script sollte das funktionieren. Dummerweise ist Apples XML "fürn Arsch"^w^w suboptimal. Wenn Dein XML allerdings auch so aussieht wie meines, d.h. daß <key>Localtion</key> und <string>der pfad</string> in einer Zeile sind, sollte es einfach gehen, ohne XML::Twig zu bemühen. Ist zwar keine saubere Lösung, aber ein gangbarer Weg.
 

stk

Grünapfel
Registriert
05.01.04
Beiträge
7.141
Moin,

Bevor ich drüber nachdenke: Bist Du sicher, daß es reicht, das auszutauschen? Die wirklichen daten holt sich iTunes doch woanders her.

Da bin ich mir in der Tat sicher, weil ich schon früher mal einzele Daten damit wieder gerade gerückt habe.

Nachtrag: Ich habe mir das jetzt bei mir mal angesehen. Mit einem Perl Script sollte das funktionieren. Dummerweise ist Apples XML "fürn Arsch"^w^w suboptimal. Wenn Dein XML allerdings auch so aussieht wie meines, d.h. daß <key>Localtion</key> und <string>der pfad</string> in einer Zeile sind, sollte es einfach gehen, ohne XML::Twig zu bemühen. Ist zwar keine saubere Lösung, aber ein gangbarer Weg.

Das Problem, das ich habe, ist weniger die einzelne Zeile (die sieht in der Tat bei mir genauso aus), sondern vielmehr, die entsprechenden Felder vorneweg passend zu parsen.

Ich experimentiere gerade, ob mir FileMakers XML-Möglichkeiten behilflich sein können …

Gruß Stefan
 

Skeeve

Pomme d'or
Registriert
26.10.05
Beiträge
3.120
Das Problem, das ich habe, ist weniger die einzelne Zeile (die sieht in der Tat bei mir genauso aus), sondern vielmehr, die entsprechenden Felder vorneweg passend zu parsen.
Och... Das ist mit Perl kein Problem. Schickst Du mir bitte ein konkretes Beispiel oder postest es hier in einem CODE Block?
 

stk

Grünapfel
Registriert
05.01.04
Beiträge
7.141
Moin,

ist (inkl. aller Tabs und Zeilenschaltungen):
Code:
		<key>8389</key>
		<dict>
			<key>Track ID</key><integer>8389</integer>
			<key>Name</key><string>A Place Called Home</string>
			<key>Artist</key><string>The March</string>
			<key>Album</key><string>Conspiracy</string>
			<key>Genre</key><string>Folk</string>
			<key>Kind</key><string>AIFF-Audiodatei</string>
			<key>Size</key><integer>230789</integer>
			<key>Total Time</key><integer>2578</integer>
			<key>Track Number</key><integer>6</integer>
			<key>Track Count</key><integer>17</integer>
			<key>Year</key><integer>1995</integer>
			<key>Date Modified</key><date>2003-12-13T06:53:50Z</date>
			<key>Date Added</key><date>2005-10-02T13:10:39Z</date>
			<key>Bit Rate</key><integer>705</integer>
			<key>Sample Rate</key><integer>44100</integer>
			<key>Play Count</key><integer>9</integer>
			<key>Play Date</key><integer>3244016422</integer>
			<key>Play Date UTC</key><date>2006-10-18T10:40:22Z</date>
			<key>Rating</key><integer>80</integer>
			<key>Persistent ID</key><string>ABE7DC6764E1497C</string>
			<key>Track Type</key><string>File</string>
			<key>Location</key><string>file://localhost/Volumes/Public/Installer/Apple%20SW/%20iLife%20Bestandteile/Apple%20Loops/Apple/Apple%20Loops%20for%20GarageBand/Blues%20Harmonica%2010.aif</string>
			<key>File Folder Count</key><integer>-1</integer>
			<key>Library Folder Count</key><integer>-1</integer>
		</dict>

sollte sein
Code:
		<key>8389</key>
		<dict>
			<key>Track ID</key><integer>8389</integer>
			<key>Name</key><string>A Place Called Home</string>
			<key>Artist</key><string>The March</string>
			<key>Album</key><string>Conspiracy</string>
			<key>Genre</key><string>Folk</string>
			<key>Kind</key><string>AIFF-Audiodatei</string>
			<key>Size</key><integer>230789</integer>
			<key>Total Time</key><integer>2578</integer>
			<key>Track Number</key><integer>6</integer>
			<key>Track Count</key><integer>17</integer>
			<key>Year</key><integer>1995</integer>
			<key>Date Modified</key><date>2003-12-13T06:53:50Z</date>
			<key>Date Added</key><date>2005-10-02T13:10:39Z</date>
			<key>Bit Rate</key><integer>705</integer>
			<key>Sample Rate</key><integer>44100</integer>
			<key>Play Count</key><integer>9</integer>
			<key>Play Date</key><integer>3244016422</integer>
			<key>Play Date UTC</key><date>2006-10-18T10:40:22Z</date>
			<key>Rating</key><integer>80</integer>
			<key>Persistent ID</key><string>ABE7DC6764E1497C</string>
			<key>Track Type</key><string>File</string>
			<key>Location</key><string>file://localhost/Volumes/Media/iTunes%20Music/The%20March/Conspiracy/06%20A%20Place%20Called%20Home.aif</string>
			<key>File Folder Count</key><integer>-1</integer>
			<key>Library Folder Count</key><integer>-1</integer>
		</dict>

zwei Dinge mehr, die mir auf- und eingefallen sind: Zum einen ist das Format nicht durchgängig, sprich je nachdem muß .aif, mp3, m4a je nach Eintrag unter <key>Kind</key> erfolgen und die Tracknummer muß mit führender Null dazu kommen.

Gruß Stefan
 

Skeeve

Pomme d'or
Registriert
26.10.05
Beiträge
3.120
Ich brauche noch eine Liste möglicher File Types, wie sie in der xml stehen, und die zugehörigen Extensions.

Außerdem werde ich keine führende Null einbauen, wenn "Track Count" nicht gefüllt ist. In dem Fall weiß ich nämlich nicht, wieviele Tracks vorhanden sind. Wenn es vorhanden ist, sollte das kein Problem sein. Es sei denn, Du sagst mir, daß IMMER genau eine führende Null erscheinen soll.

Nebenbei: Hast Du XML::Twig installiert?
 

stk

Grünapfel
Registriert
05.01.04
Beiträge
7.141
Moin,

Ich brauche noch eine Liste möglicher File Types, wie sie in der xml stehen, und die zugehörigen Extensions.

Was ich so in meiner Lib gefunden habe:

AIFF-Audiodatei = .aif
MPEG-Audiodatei = .mp3
AAC-Audiodatei = .m4a
Apple Lossless Audiodatei = .m4a
Geschützte AAC-Audiodatei = .m4p
Geschützte AAC-Audiodatei, Genre: Hörbuch & Hörspiel = .m4b

Sicher weder vollständig, noch in allen Fällen mit Fehlern behaftet.

Außerdem werde ich keine führende Null einbauen, wenn "File Folder Count" -1 ist. In dem Fall weiß ich nämlich nicht, wieviele Tracks vorhanden sind. Wenn es vorhanden ist, sollte das kein Problem sein. Es sei denn, Du sagst mir, daß IMMER genau eine führende Null erscheinen soll.

Nöö, nach genauerer Durchforstung wird das Thema nämlich noch lustiger: wenn mehr als eine CD, dann Nummerierung nämlich 1-01 … bei mehr als 09 Titel natürlich auch 10, 11, … ohne führende Null, also alles nicht so ganz ohne :(.

Nebenbei: Hast Du XML::Twig installiert?

Wenn Du mir sagst, wie ich das rausfinde, bzw. im Falle das die Antwort "Nein" heißt (was ich fast annehmen würde), wie ich das installiert bekommen, wäre mir geholfen.

Gruß Stefan
 

Skeeve

Pomme d'or
Registriert
26.10.05
Beiträge
3.120
Geschützte AAC-Audiodatei, Genre: Hörbuch & Hörspiel = .m4b
Das sieht merkwürdig aus, aber ich übernehme das so.

Nöö, nach genauerer Durchforstung wird das Thema nämlich noch lustiger: wenn mehr als eine CD, dann Nummerierung nämlich 1-01 ... bei mehr als 09 Titel natürlich auch 10, 11, ... ohne führende Null, also alles nicht so ganz ohne :(.
Wenn Du mir sagst, wie ich das erkennen kann, daß da mehr als eine CD drin ist, bau ich das auch noch ein.

Wie Du das hier zum Laufen bekommst, nehme ich an, weißt Du!?

Speichern als "stk-bib-fx", ausführbar machen, starten mit
Code:
./stk-bib-fix < Bibliothek.xml > fixed.xml
Code:
#!/usr/bin/perl
use strict;
use warnings;

my %audio_filetypes= (
	'AIFF-Audiodatei' => 'aif',
	'MPEG-Audiodatei' => 'mp3',
	'AAC-Audiodatei' => 'm4a',
	'Apple Lossless Audiodatei' => 'm4a',
	'Geschützte AAC-Audiodatei' => 'm4p',
	'Geschützte AAC-Audiodatei, Genre: Hörbuch & Hörspiel' => 'm4b',
);

my $location_ok= 'file://localhost/Volumes/Media/iTunes%20Music/';
my $new_location='file://localhost/Volumes/Media/iTunes Music/%{Artist}/%{Album}/%{Track Number} %{Name}.%{extension}';

my (
	%data,
	$text,
);
my $audio_filetype= join '|', keys %audio_filetypes;
$audio_filetype= qr/$audio_filetype/;

while (<>) {
	if ( my $hit= m(<dict>) .. m(</dict>) ) {
		if ( $hit == 1 ) {
			undef %data;
			$text= $_;
			next;
		}
		$text.= $_;
		if ( $hit ne 0+$hit ) {
			if ( $data{'Location'}=~ /^$location_ok/ ) {
				print $text;
				next;
			}
			if ( $data{'Track Count'} and $data{'Track Number'} ) {
				$data{'Track Number'}= sprintf '%0'.(length $data{'Track Count'}).'d', $data{'Track Number'};
			}
			if ( $data{'Kind'} ) {
				$data{'extension'}= $audio_filetypes{ $data{'Kind'} };
			}
			my $rewrite= $new_location;
			$data{'%'}= '%';
			$rewrite=~ s/%\{([^}]+)\}/$data{$1}/g;
			$rewrite=~ s#([^a-zA-Z0-9:/.])#sprintf('%%%02x',ord $1)#ge;
			$text=~ s#(<key>Location</key><string>)[^<]+(</string>)#$1$rewrite$2#;
			print $text;
			next;
		}
		if ( m#<key>([^<]+)</key><([^<]+)>([^<]+)</\2># ) {
			  $data{$1}= $3;
		}
	}
	else {
		print;
	}
}
 

stk

Grünapfel
Registriert
05.01.04
Beiträge
7.141
Moin,

hmm, schade, das war's wohl noch nicht ganz. Ich kriege a) reichlich Ausgaben von der Art:
Code:
Use of uninitialized value in pattern match (m//) at ./stk-bib-fx line 33, <> line 432067.
Use of uninitialized value in substitution iterator at ./stk-bib-fx line 45, <> line 432067.
Use of uninitialized value in substitution iterator at ./stk-bib-fx line 45, <> line 432067.
Use of uninitialized value in substitution iterator at ./stk-bib-fx line 45, <> line 432067.
Use of uninitialized value in substitution iterator at ./stk-bib-fx line 45, <> line 432067.
Use of uninitialized value in substitution iterator at ./stk-bib-fx line 45, <> line 432067.

Und b) einen File fixed.xml der immer noch die gleichen Fehler enthält :oops:.

Gruß Stefan
 

Skeeve

Pomme d'or
Registriert
26.10.05
Beiträge
3.120
Da sind dann wohl einige Felder unbesetzt!? Das habe ich nicht im Einzelnen abgefangen. Kanns Du mir die vollständige Datei gezippt mailen?
 

Skeeve

Pomme d'or
Registriert
26.10.05
Beiträge
3.120
Fertig!

Das Problem waren Videodateien, die selbstverfreilich keine Tracknummer haben.

Was die Mehrfach-CD Geschichte angeht: Sag mir mal ein Beispiel, dann versuche ich das auch noch einzubauen. Die Daten habe ich ja nun.

Code:
#!/usr/bin/perl
use strict;
use warnings;

my %audio_filetypes= (
	'AIFF-Audiodatei' => 'aif',
	'MPEG-Audiodatei' => 'mp3',
	'AAC-Audiodatei' => 'm4a',
	'Apple Lossless Audiodatei' => 'm4a',
	'Geschützte AAC-Audiodatei' => 'm4p',
	'Geschützte AAC-Audiodatei, Genre: Hörbuch & Hörspiel' => 'm4b',
);

my $location_ok= 'file://localhost/Volumes/Media/iTunes%20Music/';
my $new_location='file://localhost/Volumes/Media/iTunes Music/%{Artist}/%{Album}/%{Track Number} %{Name}.%{extension}';

my (
	%data,
	$text,
);
my $audio_filetype= join '|', keys %audio_filetypes;
$audio_filetype= qr/$audio_filetype/;

while (<>) {
	if ( my $hit= m(<dict>) .. m(</dict>) ) {
		if ( $hit == 1 ) {
			undef %data;
			$text= $_;
			next;
		}
		$text.= $_;
		if ( $hit ne 0+$hit ) {
			if ( not($data{'Location'})
				or $data{'Location'}=~ /^$location_ok/
				or $data{'Track Type'} ne 'File'
				or not exists $data{'extension'}
				) {
				print $text;
				next;
			}
			if ( $data{'Track Count'} ) {
				$data{'Track Number'}= sprintf '%0'.(length $data{'Track Count'}).'d', $data{'Track Number'};
			}
			if ( $data{'Kind'} ) {
				$data{'extension'}= $audio_filetypes{ $data{'Kind'} };
			}
			my $rewrite= $new_location;
			$data{'%'}= '%';
			$rewrite=~ s/%\{([^}]+)\}/$data{$1} || "* missing $1 *"/ge;
			$rewrite=~ s#([^a-zA-Z0-9:/.])#sprintf('%%%02x',ord $1)#ge;
			$text=~ s#(<key>Location</key><string>)[^<]+(</string>)#$1$rewrite$2#;
			print $text;
			next;
		}
		if ( m#<key>([^<]+)</key><([^<]+)>([^<]+)</\2># ) {
			  $data{$1}= $3;
		}
	}
	else {
		print;
	}
}
 
Zuletzt bearbeitet: