Skip to main content Skills Marketplace Discover and explore AI skills built by the community.
Install with Codex or Claude Copy this prompt, paste it into Codex, Claude, or another assistant, and let it review the skill page and install it for you.
Copy promptShow prompt details A direct command skips the review prompt. Inspect the source before running it.
npx skills add https://github.com/claude-office-skills/skills --skill batch-convertThe command stays on one line. Scroll horizontally to inspect it before copying.
Prefer a local copy? Download the files currently available to SkillsMP.
Download Zip Downloading... name batch-convert description Batch convert documents between multiple formats using a unified pipeline version 1.0 author claude-office-skills license MIT category conversion tags ["batch","conversion","bulk","automation"] department All models {"recommended":["claude-sonnet-4","claude-opus-4"],"compatible":["claude-3-5-sonnet","gpt-4","gpt-4o"]} mcp {"server":"office-mcp","tools":["batch_convert"]} capabilities ["bulk_conversion","automation"] languages ["en","zh"]
Batch Convert Skill
Overview
This skill enables batch conversion of documents between multiple formats using a unified pipeline. Convert hundreds of files at once with consistent settings, automatic format detection, and parallel processing for maximum efficiency.
How to Use
Specify the source folder or files
Choose target format(s)
Optionally configure conversion options
I'll process all files with progress tracking
Example prompts:
"Convert all PDFs in this folder to Word documents"
"Batch convert these markdown files to PDF and HTML"
"Process all Office files and convert to Markdown"
"Convert this folder of images to a single PDF"
Domain Knowledge
Supported Format Matrix
From To: DOCX To: PDF To: MD To: HTML To: PPTX DOCX - ✅ ✅ ✅ - PDF ✅ - ✅ ✅ - MD ✅ ✅ - ✅ ✅ HTML ✅ ✅ ✅ - - XLSX - ✅ ✅ ✅ - PPTX - ✅ ✅ ✅ -
Core Pipeline
from pathlib import Path
from concurrent.futures import ThreadPoolExecutor, as_completed
import subprocess
import os
class DocumentConverter :
"""Unified document conversion pipeline."""
def __init__ (self, max_workers=4 ):
self .max_workers = max_workers
.converters = {
( , ): ._md_to_docx,
( , ): ._md_to_pdf,
( , ): ._md_to_html,
( , ): ._md_to_pptx,
( , ): ._docx_to_pdf,
( , ): ._docx_to_md,
( , ): ._pdf_to_docx,
( , ): ._pdf_to_md,
( , ): ._xlsx_to_pdf,
( , ): ._xlsx_to_md,
( , ): ._pptx_to_pdf,
( , ): ._pptx_to_md,
( , ): ._html_to_md,
( , ): ._html_to_pdf,
}
( ):
input_path = Path(input_path)
input_format = input_path.suffix[ :].lower()
output_dir:
output_path = Path(output_dir) /
:
output_path = input_path.with_suffix( )
converter_key = (input_format, output_format)
converter_key .converters:
ValueError( )
converter = .converters[converter_key]
converter(input_path, output_path)
( ):
input_path = Path(input_dir)
output_path = Path(output_dir) output_dir input_path /
output_path.mkdir(exist_ok= )
recursive:
files = (input_path.rglob(file_pattern))
:
files = (input_path.glob(file_pattern))
supported_ext = [ , , , , , ]
files = [f f files f.suffix.lower() supported_ext]
results = []
ThreadPoolExecutor(max_workers= .max_workers) executor:
future_to_file = {
executor.submit( .convert, f, output_format, output_path): f
f files
}
future as_completed(future_to_file):
file = future_to_file[future]
:
result = future.result()
results.append({ : (file), : , : (result)})
Exception e:
results.append({ : (file), : , : (e)})
results
self
'md'
'docx'
self
'md'
'pdf'
self
'md'
'html'
self
'md'
'pptx'
self
'docx'
'pdf'
self
'docx'
'md'
self
'pdf'
'docx'
self
'pdf'
'md'
self
'xlsx'
'pdf'
self
'xlsx'
'md'
self
'pptx'
'pdf'
self
'pptx'
'md'
self
'html'
'md'
self
'html'
'pdf'
self
def
convert
self, input_path, output_format, output_dir=None
"""Convert single file to target format."""
1
if
f"{input_path.stem} .{output_format} "
else
f".{output_format} "
if
not
in
self
raise
f"Conversion not supported: {input_format} -> {output_format} "
self
return
def
batch_convert
self, input_dir, output_format, output_dir=None ,
file_pattern="*" , recursive=False
"""Batch convert all matching files."""
if
else
"converted"
True
if
list
else
list
'.md'
'.docx'
'.pdf'
'.xlsx'
'.pptx'
'.html'
for
in
if
in
with
self
as
self
for
in
for
in
try
'file'
str
'status'
'success'
'output'
str
except
as
'file'
str
'status'
'error'
'error'
str
return
Converter Implementations
def _md_to_docx (self, input_path, output_path ):
subprocess.run(['pandoc' , str (input_path), '-o' , str (output_path)], check=True )
return output_path
def _md_to_pdf (self, input_path, output_path ):
subprocess.run(['pandoc' , str (input_path), '-o' , str (output_path)], check=True )
return output_path
def _md_to_html (self, input_path, output_path ):
subprocess.run(['pandoc' , str (input_path), '-s' , '-o' , str (output_path)], check=True )
return output_path
def _md_to_pptx (self, input_path, output_path ):
subprocess.run(['marp' , str (input_path), '-o' , str (output_path)], check=True )
return output_path
def _docx_to_md (self, input_path, output_path ):
from markitdown import MarkItDown
md = MarkItDown()
result = md.convert(str (input_path))
with open (output_path, 'w' ) as f:
f.write(result.text_content)
return output_path
def _xlsx_to_md (self, input_path, output_path ):
from markitdown import MarkItDown
md = MarkItDown()
result = md.convert(str (input_path))
with open (output_path, 'w' ) as f:
f.write(result.text_content)
return output_path
def _pptx_to_md (self, input_path, output_path ):
from markitdown import MarkItDown
md = MarkItDown()
result = md.convert(str (input_path))
with open (output_path, 'w' ) as f:
f.write(result.text_content)
return output_path
def _pdf_to_docx (self, input_path, output_path ):
from pdf2docx import Converter
cv = Converter(str (input_path))
cv.convert(str (output_path))
cv.close()
return output_path
def _pdf_to_md (self, input_path, output_path ):
from markitdown import MarkItDown
md = MarkItDown()
result = md.convert(str (input_path))
with open (output_path, 'w' ) as f:
f.write(result.text_content)
return output_path
def _docx_to_pdf (self, input_path, output_path ):
subprocess.run([
'soffice' , '--headless' , '--convert-to' , 'pdf' ,
'--outdir' , str (output_path.parent), str (input_path)
], check=True )
return output_path
def _xlsx_to_pdf (self, input_path, output_path ):
subprocess.run([
'soffice' , '--headless' , '--convert-to' , 'pdf' ,
'--outdir' , str (output_path.parent), str (input_path)
], check=True )
return output_path
def _pptx_to_pdf (self, input_path, output_path ):
subprocess.run([
'soffice' , '--headless' , '--convert-to' , 'pdf' ,
'--outdir' , str (output_path.parent), str (input_path)
], check=True )
return output_path
Progress Tracking from tqdm import tqdm
def batch_convert_with_progress (converter, input_dir, output_format, output_dir=None ):
"""Batch convert with progress bar."""
input_path = Path(input_dir)
files = list (input_path.glob('*' ))
results = []
for file in tqdm(files, desc=f"Converting to {output_format} " ):
try :
result = converter.convert(file, output_format, output_dir)
results.append({'file' : str (file), 'status' : 'success' })
except Exception as e:
results.append({'file' : str (file), 'status' : 'error' , 'error' : str (e)})
return results
Best Practices
Test Sample First : Convert a few files before batch processing
Check Disk Space : Ensure sufficient space for output
Use Parallel Processing : Speed up with multiple workers
Handle Errors Gracefully : Log failures, continue processing
Verify Output : Spot-check converted files
Common Patterns
Format Detection Pipeline def detect_and_convert (file_path, target_format ):
"""Automatically detect format and convert."""
import mimetypes
mime_type, _ = mimetypes.guess_type(str (file_path))
format_map = {
'application/pdf' : 'pdf' ,
'application/vnd.openxmlformats-officedocument.wordprocessingml.document' : 'docx' ,
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' : 'xlsx' ,
'application/vnd.openxmlformats-officedocument.presentationml.presentation' : 'pptx' ,
'text/markdown' : 'md' ,
'text/html' : 'html' ,
}
source_format = format_map.get(mime_type, Path(file_path).suffix[1 :])
converter = DocumentConverter()
return converter.convert(file_path, target_format)
Multi-Format Output def convert_to_multiple_formats (input_file, output_formats, output_dir ):
"""Convert one file to multiple formats."""
converter = DocumentConverter()
results = {}
for fmt in output_formats:
try :
output = converter.convert(input_file, fmt, output_dir)
results[fmt] = {'status' : 'success' , 'path' : str (output)}
except Exception as e:
results[fmt] = {'status' : 'error' , 'error' : str (e)}
return results
results = convert_to_multiple_formats(
'README.md' ,
['docx' , 'pdf' , 'html' ],
'./exports'
)
Examples
Example 1: Documentation Export from pathlib import Path
import json
def export_documentation (docs_dir, export_dir ):
"""Export all documentation to multiple formats."""
converter = DocumentConverter(max_workers=8 )
docs_path = Path(docs_dir)
export_path = Path(export_dir)
for fmt in ['pdf' , 'docx' , 'html' ]:
(export_path / fmt).mkdir(parents=True , exist_ok=True )
all_results = {}
md_files = list (docs_path.rglob('*.md' ))
for md_file in md_files:
file_results = {}
for fmt in ['pdf' , 'docx' , 'html' ]:
output_dir = export_path / fmt
try :
output = converter.convert(md_file, fmt, output_dir)
file_results[fmt] = 'success'
except Exception as e:
file_results[fmt] = f'error: {e} '
all_results[str (md_file)] = file_results
print (f"Processed: {md_file.name} " )
with open (export_path / 'export_report.json' , 'w' ) as f:
json.dump(all_results, f, indent=2 )
return all_results
results = export_documentation('./docs' , './exports' )
Example 2: Legacy Document Migration def migrate_legacy_docs (source_dir, target_dir ):
"""Migrate legacy documents to modern formats."""
converter = DocumentConverter(max_workers=4 )
migrations = [
('*.doc' , 'docx' ),
('*.xls' , 'xlsx' ),
('*.ppt' , 'pptx' ),
('*.rtf' , 'docx' ),
]
source_path = Path(source_dir)
target_path = Path(target_dir)
target_path.mkdir(exist_ok=True )
total_migrated = 0
errors = []
for pattern, target_format in migrations:
files = list (source_path.glob(pattern))
for file in files:
try :
subprocess.run([
'soffice' , '--headless' ,
'--convert-to' , target_format,
'--outdir' , str (target_path),
str (file)
], check=True )
total_migrated += 1
print (f"Migrated: {file.name} " )
except Exception as e:
errors.append({'file' : str (file), 'error' : str (e)})
print (f"\nMigration complete: {total_migrated} files" )
print (f"Errors: {len (errors)} " )
return {'migrated' : total_migrated, 'errors' : errors}
Example 3: Report Generation Pipeline def generate_reports_pipeline (data_files, template_dir, output_dir ):
"""Generate reports from data files using templates."""
from datetime import datetime
converter = DocumentConverter()
output_path = Path(output_dir)
output_path.mkdir(exist_ok=True )
timestamp = datetime.now().strftime('%Y%m%d_%H%M%S' )
reports = []
for data_file in data_files:
data_path = Path(data_file)
md_content = f"""---
title: Report - {data_path.stem}
date: {datetime.now().strftime('%Y-%m-%d' )}
---
# {data_path.stem} Report
Generated: {datetime.now().strftime('%Y-%m-%d %H:%M:%S' )}
## Data Summary
"""
if data_path.suffix == '.xlsx' :
from markitdown import MarkItDown
md = MarkItDown()
result = md.convert(str (data_path))
md_content += result.text_content
md_file = output_path / f"{data_path.stem} _{timestamp} .md"
with open (md_file, 'w' ) as f:
f.write(md_content)
for fmt in ['pdf' , 'docx' ]:
try :
output = converter.convert(md_file, fmt, output_path)
reports.append({'source' : str (data_file), 'output' : str (output), 'format' : fmt})
except Exception as e:
print (f"Error converting {data_file} to {fmt} : {e} " )
return reports
Limitations
Some format combinations not supported
Complex formatting may be lost in conversion
Large files may require more time
Some conversions need external tools (LibreOffice, Pandoc)
Quality varies by source document complexity
Installation
pip install pdf2docx markitdown python-docx openpyxl
brew install pandoc
apt install pandoc
npm install -g @marp-team/marp-cli
brew install libreoffice
apt install libreoffice
Resources More from this repository
Related occupations SOC
Based on SOC occupation classification