平行文档转换 ODT > PDF Libreoffice

13 人关注

我正在将数百个ODT文件转换为PDF文件,一个接一个地做需要很长时间。我有一个多核的CPU。有没有可能用bash或python写一个脚本来并行地做这些工作? 有没有办法从命令行中用libreoffice来并行化(不知道我用的词是否正确)批量转换文档? 我一直在python/bash中做,调用以下命令。

libreoffice --headless --convert-to pdf *appsmergeme.odt
subprocess.call(str('cd $HOME; libreoffice --headless --convert-to pdf *appsmergeme.odt'), shell=True);
    
5 个评论
你是指在多个CPU上运行一个 libreoffice 命令,还是多次调用 libreoffice 并分别转换文件?在第一种情况下,你不能做任何事情,在第二种情况下,这很简单。
呃,我相信 libreoffice 会阻止你同时运行一个以上的pdf转换器。试图创建多个进程只能生成一个 .pdf 文件,其他进程都会失败。这种情况甚至在使用 --nolockcheck 选项时也会发生。所以,我相信你的问题的答案是:你不能。你应该使用一个不同的程序进行转换。
我相信我曾经读到过,libreoffice总是只使用一个进程(也是跨作家、印象派等),这就使得这可能不可能。
Bkuriu:我的意思是在多个CPU上运行libreoffice,这样就可以同时转换多个文件。
Any recommendations for doing batch conversions from the CLI ODT > PDF besides Libreoffice?
python
bash
libreoffice
timlev
timlev
发布于 2013-02-27
6 个回答
Pancho Jay
Pancho Jay
发布于 2013-03-07
已采纳
0 人赞同

你可以把libreoffice作为一个守护程序/服务来运行。请查看下面的链接,也许它也能帮助你。 启用LibreOffice服务的守护程序

Other posibility is to use unoconv ."unoconv是一个命令行工具,可以将OpenOffice可以导入的任何文件格式,转换为OpenOffice能够导出的任何文件格式。"

Danny Li
Danny Li
发布于 2013-03-07
0 人赞同

这条线或答案是旧的。 我测试了libreoffice 4.4,我可以确认我可以同时运行libreoffice。 请看我的脚本。

for odt in test*odt ; do
echo $odt
soffice --headless --convert-to pdf $odt & 
ps -ef|grep ffice 
    
Chickenmarkus
Chickenmarkus
发布于 2013-03-07
0 人赞同

既然作者已经介绍了Python是一个有效的答案。

import subprocess
import os, glob
from multiprocessing.dummy import Pool    # wrapper around the threading module
def worker(fname, dstdir=os.path.expanduser("~")):
    subprocess.call(["libreoffice", "--headless", "--convert-to", "pdf", fname],
                    cwd=dstdir)
pool = Pool()
pool.map(worker, glob.iglob(
        os.path.join(os.path.expanduser("~"), "*appsmergeme.odt")

通过multiprocessing.dummy使用线程池而不是进程池就足够了,因为无论如何,用于真正并行的新进程是由subprocess.call()生成的。

我们可以直接设置命令以及当前工作目录cwd。不需要为每个文件加载一个shell就可以做到这一点。此外,os.path可以实现跨平台的互操作性。

luca76
luca76
发布于 2013-03-07
0 人赞同

我在golang中写了一个程序,可以批量转换成千上万的doc/xls文件。

  • define the "root" variable value to the path of your documents to convert
  • already converted documents to pdf are skipped (if not, comment the check condition in the visit() function)
  • here I'm using 4 threads (I have an Intel i3 with 4 cores). You can modify the value in the main() function
  • 有时会发生Libreoffice不能转换某些文件的情况,所以你应该打开它并手动将它们转换为PDF。幸运的是,在我的16.000个文件中,只有10个需要转换。

    package main
    import (
        "os/exec"
        "sync"
        "path/filepath"
        "fmt"
        "strings"
    // root dir of your documents to convert
    root := "/.../conversion-from-office/"
    var tasks = make(chan *exec.Cmd, 64)
    func visit(path string, f os.FileInfo, err error) error {
        if (f.IsDir()) {
            // fmt.Printf("Entering %s\n", path)
        } else {
            ext := filepath.Ext(path)
            if (strings.ToLower (ext) == "pdf") {
            } else {
                outfile := path[0:len(path)-len(ext)] + ".pdf"
                if _, err := os.Stat(outfile); os.IsNotExist(err) {
                    fmt.Printf("Converting %s\n", path)
                    outdir := filepath.Dir(path)
                    tasks <- exec.Command("soffice", "--headless", "--convert-to", "pdf", path, "--outdir", outdir)
        return nil
    func main() {
        // spawn four worker goroutines
        var wg sync.WaitGroup
        // the  ...; i < 4;... indicates that I'm using 4 threads
        for i := 0; i < 4; i++ {
            wg.Add(1)
            go func() {
                for cmd := range tasks {
                    cmd.Run()
                wg.Done()
        err := filepath.Walk(root, visit)
        fmt.Printf("filepath.Walk() returned %v\n", err)
        close(tasks)
        // wait for the workers to finish
        wg.Wait()
        
    abhayAndPoorvisDad
    abhayAndPoorvisDad
    发布于 2013-03-07
    0 人赞同

    我们有一个类似的问题,就是 unoconv . unoconv 内部使用了 libreoffice .我们通过在一次调用中向unoconv发送多个文件来解决这个问题。因此,我们不是在所有的文件上进行迭代,而是将文件集分成桶,每个桶代表o/p格式。然后,我们对有多少个桶就调用多少次。

    我很确定 libreoffice 也有一个类似的模式。

    BRPocock
    BRPocock
    发布于 2013-03-07
    0 人赞同

    Untested 有可能是有效的。

    你/可能/能够。

  • Divide up the files into a number of parallel batches in some equitable way, e.g. placing them all in folders;
  • Create a distinct local user account to handle each folder;
  • Run Libreoffice serially as each user
  •  for paralleluser in timlev1 timlev2 timlev3 timlev4 ; do
          su - $paralleluser -c \
             "for file in /var/spool/pdfbatches/$paralleluser ; do \
                libreoffice --headless --convert-to pdf $file ; done"