Ebook Konversion via Kommando-Zeile mit Calibre

riff-raff

Captain
Registriert
Jan. 2009
Beiträge
3.924
Ich würde gern meine Ebook-Datenbank komplett vom Format EPUB in MOBI umwandeln. Calibre läuft headless als Server-Instanz auf einem Debian-NAS.

Die Ebooks liegen alle jeweils in Unterordnern
Code:
/media/xxx/ebooks/'autor'/'buchtitel'

rekrusiv sollen alle Ordner abgearbeitet werden und jeweils im passenden Ordner das entsprechend umgewandelte MOBI-File mit eingereiht werden.

Code:
find /media/xxx/ebooks/ -name "*.epub*" -print0 | xargs -0 ebook-convert -t
ist mein Ansatz, allerdings fehlt noch die Zuordnung des Formates und des Ortes für die Ausgabe.

Der Synthax schaut wie folgt aus:
Code:
ebook-convert myfile.input_format myfile.output_format -h

Irgendwie steh ich auf dem Schlauch und komm nicht weiter mit der Benennung und dem File-Format :(

Edit: Zusätzlich wäre noch schön, wenn ich die Worker auf 2 Threads beschränken kann. Ich vermute das sollte via config-file möglich sein.
 
Zuletzt bearbeitet:
Deine Frage ist also, wie du neben dem einen weitergegebenen Argument von find auch noch den Dateistring verändern kannst, sodass dann z.b. "./abc.epub" und "./abc.mobi" als Argument für ebook-convert stehen?

Ich würde das (bin jetzt auch kein bash-Experte, also eher klassische Programmierweise) mit dem Ansatz lösen:
Code:
#!/bin/bash
IFS=$'\n'
for file in `find -type f -name "*.epub"`
do
	ebook-convert "$file" "${file%epub}mobi"
done

${file%epub} entfernt in der Variable file den substring "epub", der dann eben durch mobi ersetzt wird.
 
Sind relative Pfade zu berücksichtigen? Wie setze ich das rekrusive Abarbeiten der Unterordner um?
 
Nunja, da ja bereits im Eingangspost der Befehl find erwähnt wurde, bin ich davon ausgegangen, dass bekannt ist, dass er ja vom spezifizierten Pfad ausgehend alle Unterverzeichnisse und deren Dateien auflistet (auch abhängig davon nur die relativen oder die absoluten Pfade), so gesehen ist in dieser Hinsicht keine weitere Arbeit notwendig.

Relative Pfade sind also insofern also nicht zu berücksichtigen, da durch
Code:
find /media/xxx/ebooks
ohnehin die absoluten Pfade verwendet werden.

Da ja zu jeder Datei nur die Endung verändert wird, und der Rest des Pfades unangetastet bleibt, befinden sich die Zieldateien wieder im entsprechenden Ordner der ursprünglichen Datei.

Testen würde ich so einen Befehl vorher durch einen 'dry run' des entsprechenden Programms, falls verfügbar, sonst durch Ersetzen des ausführenden Befehls durch echo, ob auch tatsächlich alle gewünschten und keine anderen Dateien betroffen sind - so erhält man schnell eine Übersicht und Klarheit.
 
Die Rückfrage bezüglich der relativen Pfade kam eher nachdem mir immer wieder die Meldung "directory not found" ausgegeben wurde. Problem mittlerweile schon gelöst, hatte das Script an einem Windows-PC erstellt, es beinhaltete ein Windows-Zeilenende. ;)

Soweit läuft das Script und tut was es soll, es wird einer von 4 Kernen genutzt, was meinem Anliegen sehr entgegenkommt. Ich würde gern im Zug der Erstellung der MOBI-Files gleich noch den Besitzer ändern:

Code:
/opt/calibre/ebook-convert "$file" "${file%epub}mobi" & chown calibre:users "${file%epub}mobi"

tut aber leider nicht was es soll :(

Edit: Ein "&" vergessen, jetzt läuft es. ;)
Gut wäre auch noch ein Check, ob in dem Ordner bereits eine Mobi vorhanden ist.

Edit2: Leider erkennt der Calibre-Server die Mobis nicht, bzw. bietet diese via Web-Frotent nicht an. Auch ein Restart des Server-Prozesses hilft nicht.
 
Zuletzt bearbeitet:
Also zum ersten Problem, ob bereits eine .mobi vorhanden ist, kann ich nur allgemein auf die Bash-Sprache verweisen. Dazu gibt es genügend Literatur im Netz. In diesem Fall lässt sich unter dem Stichwort Verzweigung sicher schnell eine Lösung erstellen.

Wie und ob Calibre selbst funktioniert, kann ich leider nicht sagen, damit habe ich mich selbst erst rudimentär beschäftigt.
 
Mit ner einfachen if/then/else-Schleife bekomme ich den Check gelöst, am calibre-server bastel ich gerad, mal sehen, ob ich den zur Zusammenarbeit überreden kann. ;)

Edit: Eigentlich viel zu umständlich, kann ich nicht bei der
Code:
find -type f -name "*.epub"
ein zweites Kriterium anhängen?
Code:
find -type f -name "*.epub" && file ! "${file%epub}mobi"

Edit: Das Hinzufügen zur Datenbank erfolgt mittels
Code:
calibredb add_format --with-library=/media/xxx/calibre/ book-id /media/xxx/calibre/author/book-title/book-title.mobi

Die book-id kann man dem Unterordner-Namen "Buchtitel (ID)" entnehmen, den wechselnden, relativen Pfad zu jedem einzelnen MOBI-File bekomm ich allerdings nicht hin, da hier
Code:
"${file%epub}mobi"
versagt.
 
Zuletzt bearbeitet:
Ich empfehle gerne nochmal den Test durch ein einfaches echo um zu überprüfen, welche Dateinamen nun tatsächlich verwendet werden.

Inwiefern "versagt" der Zugriff auf die Variable?
Nach der Erstellung der .mobi Dateien ist ja die Substitution von .epub durch .mobi im Dateinamen nicht mehr notwendig, da kann find ja gleich alle .mobi suchen und sie der Datenbank hinzufügen...
 
Code:
#!/bin/bash
IFS=$'\n'
for file in `find /media/xxx/calibre/ -type f -name "*.epub"`
do
echo "$file"
done

gibt für alle gefundenen EPUBs den vollständigen Pfad aus; dementsprechend
Code:
"${file%epub}mobi"
natürlich mit MOBI. Das kann ich also für die Aktualisierung der DB hernehmen.
Nun fehlt es nur noch an den IDs, welche wie gesagt immer die letzten Zeichen des übergeordneten Ordners sind. Bsp.
/media/xxx/calibre/Martin_Luther/Bibel_(371)/Martin_Luther_-_Bibel.mobi
Wobei die 371 die ID wäre. Mit
Code:
dirname
komm ich zwar an den Ordnernamen, allerdings nicht an bestimmte Teile davon.


Das Problem mit der Suche nach vorhandenen MOBIs ist gar nicht mal so wichtig, da aktell in der DB noch keine sind bzw. die vorhandenen einfach gelöscht werden können und das Script einfach nochmal neue erstellen kann, auf 1-2 Stunden kommt es da nicht an.
 
Zuletzt bearbeitet:
Das sollte sich einfach raus RegEx-en lassen,
Code:
idstring=`dirname "/media/xxx/calibre/Martin_Luther/Bibel_(371)/Martin_Luther_-_Bibel.mobi"`
echo $idstring | grep -oP "\(\K\d*"
andernfalls reicht auch analog zu vorher
Code:
idstring=`dirname "/media/xxx/calibre/Martin_Luther/Bibel_(371)/Martin_Luther_-_Bibel.mobi"`
idstring=${idstring%\)}
id=${idstring##*\(}
 
Code:
idstring=`dirname "${file%epub}mobi"`
echo $idstring | grep -oP "\(\K\d*"
liefert die passenden IDs

Code:
#!/bin/bash
IFS=$'\n'
for file in `find /media/xxx/calibre/ -type f -name "*.epub"`
do
    /opt/calibre/ebook-convert "$file" "${file%epub}mobi" && chown calibre:users "${file%epub}mobi"
    idstring=`dirname "${file%epub}mobi"`
    idstring=${idstring%\)}
    /opt/calibre/calibredb add_format --with-library=/media/xxx/calibre/ ${idstring##*\(} "${file%epub}mobi"
done
läuft gerade, ich teste es an 20 ebooks, mal schauen, ob es tut was es soll.

Wenn es durchgelaufen ist melde ich mich nochmal ;)

Edit:
Script läuft und macht was es soll!
TAUSEND DANK! Deinen Pfadfinder-Orden für eine gute Tat hast du für heute auf jeden Fall verdient! :D


Edit 19.02.17
Nun muss ich das "Fass" doch nochmal aufmachen:

Ich habe das Script im Kleinen getestet und auf ~100 Ebooks in einer kleinen Bibliothek. Dazu die Prüfung, ob eine MOBI vorhanden ist.

Code:
#!/bin/bash
IFS=$'\n'
for file in `find /media/xxx/calibre/ -type f -name "*.epub"`
do
 if [ ! -f "${file%epub}mobi" ]
 then
  /opt/calibre/ebook-convert "$file" "${file%epub}mobi" && chown calibre:users "${file%epub}mobi"
  idstring=`dirname "${file%epub}mobi"`
  idstring=${idstring%\)}
  /opt/calibre/calibredb add_format --with-library=/media/xxx/calibre/ ${idstring##*\(} "${file%epub}mobi"
 fi
done

Funktioniert auf die kleine Datenbank gut, wenn ich die aber auf die "große" anwende werden z.T. MOBIs in einem Unterordner doppelt angelegt und auch noch mit anderem Namensschema, allerdings offensichtlich das gleiche Buch wie die EPUB-Quelle. Bsp:

"Klaus Müller - Meine Biographie.epub" ist die Quelle

Das Script legt

"Klaus Müller - Meine Biographie.mobi" im gleichen Ordner an und trägt sie in die DB ein

dann findet ich da aber auch noch

"Müller-Klaus - Biographie.mobi"

Das tritt nicht bei allen Büchern auf, die "anderen" MOBIs sind vor Start des Scripts nicht vorhanden. Die MOBIs eines Buches werden auch nicht gleichzeitig oder nacheinander angelegt sondern irgendwann (schwer nachvollziehbar bei >2k Büchern)
 
Zuletzt bearbeitet:
Zurück
Oben