我正在将数百个ODT文件转换为PDF文件,并且需要很长时间才能一个接一个地执行。我有一个多核CPU。是否可以使用bash或python编写脚本来并行执行这些操作? 有没有办法从命令行使用libreoffice并行化(不确定我是否使用正确的单词)批量文档转换? 我一直在python / bash中调用以下命令:
libreoffice --headless --convert-to pdf *appsmergeme.odt
OR
subprocess.call(str('cd $HOME; libreoffice --headless --convert-to pdf *appsmergeme.odt'), shell=True);
谢谢!
添
答案 0 :(得分:3)
您可以将libreoffice作为守护程序/服务运行。请检查以下链接,也许它也有帮助:Daemonize the LibreOffice service
其他可能性是使用unoconv。 “unoconv是一个命令行实用程序,可以将OpenOffice可以导入的任何文件格式转换为OpenOffice能够导出的任何文件格式。”
答案 1 :(得分:1)
这个帖子或答案都是旧的。 我测试了libreoffice 4.4,我可以确认我可以同时运行libreoffice。 看我的剧本。
for odt in test*odt ; do
echo $odt
soffice --headless --convert-to pdf $odt &
ps -ef|grep ffice
done
答案 2 :(得分:0)
我在golang中编写了一个程序来批量转换成千上万个doc / xls文件。
有时可能会发生Libreoffice没有转换某些文件,因此您应该打开它并手动将它们转换为PDF。幸运的是,他们在我的16.000个文件中只有10个要转换。
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()
}
答案 3 :(得分:0)
我们遇到与 unoconv 类似的问题。 unoconv 在内部使用 libreoffice 。我们通过在一次调用中将多个文件发送到unoconv来解决它。因此,我们只是将文件集分区为桶,而不是迭代所有文件,每个桶代表o / p格式。然后我们拨打和桶一样多的电话。
我很确定 libreoffice 也有类似的模式。
答案 4 :(得分: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
支持跨平台互操作性。
答案 5 :(得分:-1)
未经测试可能有效:
您/可能/能够:
e.g。
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绑定的任务,因此每个CPU核心运行1可能不非常快。