我将数以百计的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);
谢谢!
蒂姆
你可以作为一个守护进程/服务运行的LibreOffice。 请检查下面的链接,也许它可以帮助你太: 守护进程的LibreOffice的服务
其他posibility是使用unoconv 。 “unoconv是一个命令行实用工具,可以将任何文件格式的OpenOffice可以导入到任何文件格式,OpenOffice是可以导出的。”
这个线程或答案是旧的。 我测试的LibreOffice 4.4,我可以确认我可以同时运行的LibreOffice。 看到我的脚本。
for odt in test*odt ; do echo $odt soffice --headless --convert-to pdf $odt & ps -ef|grep ffice done
我在golang批量编写的程序转换成千上万的DOC / XLS文件。
- 定义“根”变量值的文件的路径转换
- 已经转换为PDF文件被跳过(如果没有,在访问()函数评论检验条件)
- 在这里我使用4个线程(我有一个英特尔酷睿i3 4个核心)。 您可以在main()函数修改值
有时,它可能发生的LibreOffice不转换某些文件,所以你应该打开它,并将其手动转换为PDF。 幸运的是,他们只是10我的16.000文件转换的。
package main
import (
"os/exec"
"sync"
"path/filepath"
"os"
"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()
}
我们与unoconv类似的问题。 unoconv内部利用的LibreOffice的。 我们通过发送多个文件中的一个调用到unoconv解决了这个问题。 因此,而不是遍历所有的文件,我们只是分区的文件组到水桶,占O / P格式每个桶。 然后我们作出有桶尽可能多地调用。
我敢肯定的LibreOffice也有类似的模式。
由于笔者已经介绍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
支持跨平台的互操作性。
未经测试的潜在有效:
你/可/能够:
- 瓜分文件分成若干部分公平的方式,如平行批次将他们所有的文件夹;
- 创建一个独特的本地用户帐户来处理每个文件夹;
- 运行连续的LibreOffice每个用户
如
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"
done
通过使用su -
你会不小心从您的实际会话继承任何环境变量,所以并行进程不应该彼此(从争夺资源除外)干扰。
请记住,这些都是有可能的I / O密集型任务,所以运行1每个CPU核心可能不会加速到你的意思非常多。