├── .gitignore
├── .idea
└── .idea.PdfMerge
│ └── .idea
│ ├── .gitignore
│ ├── encodings.xml
│ ├── git_toolbox_blame.xml
│ ├── indexLayout.xml
│ ├── misc.xml
│ └── vcs.xml
├── LICENSE
├── PdfMerge.sln
├── PdfMerge
├── PdfMerge.csproj
├── Program.cs
└── icon.ico
├── README.md
└── icon.png
/.gitignore:
--------------------------------------------------------------------------------
1 | ### ASPNETCore template
2 | ## Ignore Visual Studio temporary files, build results, and
3 | ## files generated by popular Visual Studio add-ons.
4 |
5 | # User-specific files
6 | *.suo
7 | *.user
8 | *.userosscache
9 | *.sln.docstates
10 |
11 | # User-specific files (MonoDevelop/Xamarin Studio)
12 | *.userprefs
13 |
14 | # Build results
15 | [Dd]ebug/
16 | [Dd]ebugPublic/
17 | [Rr]elease/
18 | [Rr]eleases/
19 | x64/
20 | x86/
21 | bld/
22 | [Bb]in/
23 | [Oo]bj/
24 | [Ll]og/
25 |
26 | # Visual Studio 2015 cache/options directory
27 | .vs/
28 | # Uncomment if you have tasks that create the project's static files in wwwroot
29 | #wwwroot/
30 |
31 | # MSTest test Results
32 | [Tt]est[Rr]esult*/
33 | [Bb]uild[Ll]og.*
34 |
35 | # NUNIT
36 | *.VisualState.xml
37 | TestResult.xml
38 |
39 | # Build Results of an ATL Project
40 | [Dd]ebugPS/
41 | [Rr]eleasePS/
42 | dlldata.c
43 |
44 | # DNX
45 | project.lock.json
46 | project.fragment.lock.json
47 | artifacts/
48 |
49 | *_i.c
50 | *_p.c
51 | *_i.h
52 | *.ilk
53 | *.meta
54 | *.obj
55 | *.pch
56 | *.pdb
57 | *.pgc
58 | *.pgd
59 | *.rsp
60 | *.sbr
61 | *.tlb
62 | *.tli
63 | *.tlh
64 | *.tmp
65 | *.tmp_proj
66 | *.log
67 | *.vspscc
68 | *.vssscc
69 | .builds
70 | *.pidb
71 | *.svclog
72 | *.scc
73 |
74 | # Chutzpah Test files
75 | _Chutzpah*
76 |
77 | # Visual C++ cache files
78 | ipch/
79 | *.aps
80 | *.ncb
81 | *.opendb
82 | *.opensdf
83 | *.sdf
84 | *.cachefile
85 | *.VC.db
86 | *.VC.VC.opendb
87 |
88 | # Visual Studio profiler
89 | *.psess
90 | *.vsp
91 | *.vspx
92 | *.sap
93 |
94 | # TFS 2012 Local Workspace
95 | $tf/
96 |
97 | # Guidance Automation Toolkit
98 | *.gpState
99 |
100 | # ReSharper is a .NET coding add-in
101 | _ReSharper*/
102 | *.[Rr]e[Ss]harper
103 | *.DotSettings.user
104 |
105 | # JustCode is a .NET coding add-in
106 | .JustCode
107 |
108 | # TeamCity is a build add-in
109 | _TeamCity*
110 |
111 | # DotCover is a Code Coverage Tool
112 | *.dotCover
113 |
114 | # Visual Studio code coverage results
115 | *.coverage
116 | *.coveragexml
117 |
118 | # NCrunch
119 | _NCrunch_*
120 | .*crunch*.local.xml
121 | nCrunchTemp_*
122 |
123 | # MightyMoose
124 | *.mm.*
125 | AutoTest.Net/
126 |
127 | # Web workbench (sass)
128 | .sass-cache/
129 |
130 | # Installshield output folder
131 | [Ee]xpress/
132 |
133 | # DocProject is a documentation generator add-in
134 | DocProject/buildhelp/
135 | DocProject/Help/*.HxT
136 | DocProject/Help/*.HxC
137 | DocProject/Help/*.hhc
138 | DocProject/Help/*.hhk
139 | DocProject/Help/*.hhp
140 | DocProject/Help/Html2
141 | DocProject/Help/html
142 |
143 | # Click-Once directory
144 | publish/
145 |
146 | # Publish Web Output
147 | *.[Pp]ublish.xml
148 | *.azurePubxml
149 | # TODO: Comment the next line if you want to checkin your web deploy settings
150 | # but database connection strings (with potential passwords) will be unencrypted
151 | *.pubxml
152 | *.publishproj
153 |
154 | # Microsoft Azure Web App publish settings. Comment the next line if you want to
155 | # checkin your Azure Web App publish settings, but sensitive information contained
156 | # in these scripts will be unencrypted
157 | PublishScripts/
158 |
159 | # NuGet Packages
160 | *.nupkg
161 | # The packages folder can be ignored because of Package Restore
162 | **/packages/*
163 | # except build/, which is used as an MSBuild target.
164 | !**/packages/build/
165 | # Uncomment if necessary however generally it will be regenerated when needed
166 | #!**/packages/repositories.config
167 | # NuGet v3's project.json files produces more ignoreable files
168 | *.nuget.props
169 | *.nuget.targets
170 |
171 | # Microsoft Azure Build Output
172 | csx/
173 | *.build.csdef
174 |
175 | # Microsoft Azure Emulator
176 | ecf/
177 | rcf/
178 |
179 | # Windows Store app package directories and files
180 | AppPackages/
181 | BundleArtifacts/
182 | Package.StoreAssociation.xml
183 | _pkginfo.txt
184 |
185 | # Visual Studio cache files
186 | # files ending in .cache can be ignored
187 | *.[Cc]ache
188 | # but keep track of directories ending in .cache
189 | !*.[Cc]ache/
190 |
191 | # Others
192 | ClientBin/
193 | ~$*
194 | *~
195 | *.dbmdl
196 | *.dbproj.schemaview
197 | *.jfm
198 | *.pfx
199 | *.publishsettings
200 | node_modules/
201 | orleans.codegen.cs
202 |
203 | # Since there are multiple workflows, uncomment next line to ignore bower_components
204 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
205 | #bower_components/
206 |
207 | # RIA/Silverlight projects
208 | Generated_Code/
209 |
210 | # Backup & report files from converting an old project file
211 | # to a newer Visual Studio version. Backup files are not needed,
212 | # because we have git ;-)
213 | _UpgradeReport_Files/
214 | Backup*/
215 | UpgradeLog*.XML
216 | UpgradeLog*.htm
217 |
218 | # SQL Server files
219 | *.mdf
220 | *.ldf
221 |
222 | # Business Intelligence projects
223 | *.rdl.data
224 | *.bim.layout
225 | *.bim_*.settings
226 |
227 | # Microsoft Fakes
228 | FakesAssemblies/
229 |
230 | # GhostDoc plugin setting file
231 | *.GhostDoc.xml
232 |
233 | # Node.js Tools for Visual Studio
234 | .ntvs_analysis.dat
235 |
236 | # Visual Studio 6 build log
237 | *.plg
238 |
239 | # Visual Studio 6 workspace options file
240 | *.opt
241 |
242 | # Visual Studio LightSwitch build output
243 | **/*.HTMLClient/GeneratedArtifacts
244 | **/*.DesktopClient/GeneratedArtifacts
245 | **/*.DesktopClient/ModelManifest.xml
246 | **/*.Server/GeneratedArtifacts
247 | **/*.Server/ModelManifest.xml
248 | _Pvt_Extensions
249 |
250 | # Paket dependency manager
251 | .paket/paket.exe
252 | paket-files/
253 |
254 | # FAKE - F# Make
255 | .fake/
256 |
257 | # JetBrains Rider
258 | .idea/
259 | *.sln.iml
260 |
261 | # CodeRush
262 | .cr/
263 |
264 | # Python Tools for Visual Studio (PTVS)
265 | __pycache__/
266 | *.pyc
267 |
268 | # Cake - Uncomment if you are using it
269 | # tools/
270 |
271 | ### VisualStudio template
272 | ## Ignore Visual Studio temporary files, build results, and
273 | ## files generated by popular Visual Studio add-ons.
274 | ##
275 | ## Get latest from https://github.com/github/gitignore/blob/main/VisualStudio.gitignore
276 |
277 | # User-specific files
278 | *.rsuser
279 |
280 | # User-specific files (MonoDevelop/Xamarin Studio)
281 |
282 | # Mono auto generated files
283 | mono_crash.*
284 |
285 | # Build results
286 | [Ww][Ii][Nn]32/
287 | [Aa][Rr][Mm]/
288 | [Aa][Rr][Mm]64/
289 | [Ll]ogs/
290 |
291 | # Visual Studio 2015/2017 cache/options directory
292 | # Uncomment if you have tasks that create the project's static files in wwwroot
293 | #wwwroot/
294 |
295 | # Visual Studio 2017 auto generated files
296 | Generated\ Files/
297 |
298 | # MSTest test Results
299 |
300 | # NUnit
301 | nunit-*.xml
302 |
303 | # Build Results of an ATL Project
304 |
305 | # Benchmark Results
306 | BenchmarkDotNet.Artifacts/
307 |
308 | # .NET Core
309 |
310 | # ASP.NET Scaffolding
311 | ScaffoldingReadMe.txt
312 |
313 | # StyleCop
314 | StyleCopReport.xml
315 |
316 | # Files built by Visual Studio
317 | *_h.h
318 | *.iobj
319 | *.ipdb
320 | *_wpftmp.csproj
321 | *.tlog
322 |
323 | # Chutzpah Test files
324 |
325 | # Visual C++ cache files
326 |
327 | # Visual Studio profiler
328 |
329 | # Visual Studio Trace Files
330 | *.e2e
331 |
332 | # TFS 2012 Local Workspace
333 |
334 | # Guidance Automation Toolkit
335 |
336 | # ReSharper is a .NET coding add-in
337 |
338 | # TeamCity is a build add-in
339 |
340 | # DotCover is a Code Coverage Tool
341 |
342 | # AxoCover is a Code Coverage Tool
343 | .axoCover/*
344 | !.axoCover/settings.json
345 |
346 | # Coverlet is a free, cross platform Code Coverage Tool
347 | coverage*.json
348 | coverage*.xml
349 | coverage*.info
350 |
351 | # Visual Studio code coverage results
352 |
353 | # NCrunch
354 |
355 | # MightyMoose
356 |
357 | # Web workbench (sass)
358 |
359 | # Installshield output folder
360 |
361 | # DocProject is a documentation generator add-in
362 |
363 | # Click-Once directory
364 |
365 | # Publish Web Output
366 | # Note: Comment the next line if you want to checkin your web deploy settings,
367 | # but database connection strings (with potential passwords) will be unencrypted
368 |
369 | # Microsoft Azure Web App publish settings. Comment the next line if you want to
370 | # checkin your Azure Web App publish settings, but sensitive information contained
371 | # in these scripts will be unencrypted
372 |
373 | # NuGet Packages
374 | # NuGet Symbol Packages
375 | *.snupkg
376 | # The packages folder can be ignored because of Package Restore
377 | **/[Pp]ackages/*
378 | # except build/, which is used as an MSBuild target.
379 | !**/[Pp]ackages/build/
380 | # Uncomment if necessary however generally it will be regenerated when needed
381 | #!**/[Pp]ackages/repositories.config
382 | # NuGet v3's project.json files produces more ignorable files
383 |
384 | # Microsoft Azure Build Output
385 |
386 | # Microsoft Azure Emulator
387 |
388 | # Windows Store app package directories and files
389 | *.appx
390 | *.appxbundle
391 | *.appxupload
392 |
393 | # Visual Studio cache files
394 | # files ending in .cache can be ignored
395 | # but keep track of directories ending in .cache
396 | !?*.[Cc]ache/
397 |
398 | # Others
399 |
400 | # Including strong name files can present a security risk
401 | # (https://github.com/github/gitignore/pull/2483#issue-259490424)
402 | #*.snk
403 |
404 | # Since there are multiple workflows, uncomment next line to ignore bower_components
405 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
406 | #bower_components/
407 |
408 | # RIA/Silverlight projects
409 |
410 | # Backup & report files from converting an old project file
411 | # to a newer Visual Studio version. Backup files are not needed,
412 | # because we have git ;-)
413 | ServiceFabricBackup/
414 | *.rptproj.bak
415 |
416 | # SQL Server files
417 | *.ndf
418 |
419 | # Business Intelligence projects
420 | *.rptproj.rsuser
421 | *- [Bb]ackup.rdl
422 | *- [Bb]ackup ([0-9]).rdl
423 | *- [Bb]ackup ([0-9][0-9]).rdl
424 |
425 | # Microsoft Fakes
426 |
427 | # GhostDoc plugin setting file
428 |
429 | # Node.js Tools for Visual Studio
430 |
431 | # Visual Studio 6 build log
432 |
433 | # Visual Studio 6 workspace options file
434 |
435 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
436 | *.vbw
437 |
438 | # Visual Studio 6 auto-generated project file (contains which files were open etc.)
439 | *.vbp
440 |
441 | # Visual Studio 6 workspace and project file (working project files containing files to include in project)
442 | *.dsw
443 | *.dsp
444 |
445 | # Visual Studio 6 technical files
446 |
447 | # Visual Studio LightSwitch build output
448 |
449 | # Paket dependency manager
450 |
451 | # FAKE - F# Make
452 |
453 | # CodeRush personal settings
454 | .cr/personal
455 |
456 | # Python Tools for Visual Studio (PTVS)
457 |
458 | # Cake - Uncomment if you are using it
459 | # tools/**
460 | # !tools/packages.config
461 |
462 | # Tabs Studio
463 | *.tss
464 |
465 | # Telerik's JustMock configuration file
466 | *.jmconfig
467 |
468 | # BizTalk build output
469 | *.btp.cs
470 | *.btm.cs
471 | *.odx.cs
472 | *.xsd.cs
473 |
474 | # OpenCover UI analysis results
475 | OpenCover/
476 |
477 | # Azure Stream Analytics local run output
478 | ASALocalRun/
479 |
480 | # MSBuild Binary and Structured Log
481 | *.binlog
482 |
483 | # NVidia Nsight GPU debugger configuration file
484 | *.nvuser
485 |
486 | # MFractors (Xamarin productivity tool) working folder
487 | .mfractor/
488 |
489 | # Local History for Visual Studio
490 | .localhistory/
491 |
492 | # Visual Studio History (VSHistory) files
493 | .vshistory/
494 |
495 | # BeatPulse healthcheck temp database
496 | healthchecksdb
497 |
498 | # Backup folder for Package Reference Convert tool in Visual Studio 2017
499 | MigrationBackup/
500 |
501 | # Ionide (cross platform F# VS Code tools) working folder
502 | .ionide/
503 |
504 | # Fody - auto-generated XML schema
505 | FodyWeavers.xsd
506 |
507 | # VS Code files for those working on multiple tools
508 | .vscode/*
509 | !.vscode/settings.json
510 | !.vscode/tasks.json
511 | !.vscode/launch.json
512 | !.vscode/extensions.json
513 | *.code-workspace
514 |
515 | # Local History for Visual Studio Code
516 | .history/
517 |
518 | # Windows Installer files from build outputs
519 | *.cab
520 | *.msi
521 | *.msix
522 | *.msm
523 | *.msp
524 |
525 | # JetBrains Rider
526 |
527 |
--------------------------------------------------------------------------------
/.idea/.idea.PdfMerge/.idea/.gitignore:
--------------------------------------------------------------------------------
1 | # Default ignored files
2 | /shelf/
3 | /workspace.xml
4 | # Rider ignored files
5 | /contentModel.xml
6 | /.idea.PdfMerge.iml
7 | /modules.xml
8 | /projectSettingsUpdater.xml
9 | # Editor-based HTTP Client requests
10 | /httpRequests/
11 | # Datasource local storage ignored files
12 | /dataSources/
13 | /dataSources.local.xml
14 |
--------------------------------------------------------------------------------
/.idea/.idea.PdfMerge/.idea/encodings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/.idea/.idea.PdfMerge/.idea/git_toolbox_blame.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.idea/.idea.PdfMerge/.idea/indexLayout.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/.idea/.idea.PdfMerge/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.idea/.idea.PdfMerge/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2025 Johannes Ebner
2 |
3 | MIT License
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a
6 | copy of this software and associated documentation files (the "Software"),
7 | to deal in the Software without restriction, including without limitation
8 | the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 | and/or sell copies of the Software, and to permit persons to whom the
10 | Software is furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included
13 | in all copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 | THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 | DEALINGS IN THE SOFTWARE.
--------------------------------------------------------------------------------
/PdfMerge.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PdfMerge", "PdfMerge\PdfMerge.csproj", "{3C0A707D-F244-4BF9-8591-8A60596D80F5}"
4 | EndProject
5 | Global
6 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
7 | Debug|Any CPU = Debug|Any CPU
8 | Release|Any CPU = Release|Any CPU
9 | EndGlobalSection
10 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
11 | {3C0A707D-F244-4BF9-8591-8A60596D80F5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
12 | {3C0A707D-F244-4BF9-8591-8A60596D80F5}.Debug|Any CPU.Build.0 = Debug|Any CPU
13 | {3C0A707D-F244-4BF9-8591-8A60596D80F5}.Release|Any CPU.ActiveCfg = Release|Any CPU
14 | {3C0A707D-F244-4BF9-8591-8A60596D80F5}.Release|Any CPU.Build.0 = Release|Any CPU
15 | EndGlobalSection
16 | EndGlobal
17 |
--------------------------------------------------------------------------------
/PdfMerge/PdfMerge.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | net9.0
6 | enable
7 | enable
8 | true
9 | true
10 | icon.ico
11 | Johannes Ebner
12 | https://github.com/Structed/PdfMerge
13 | https://github.com/Structed/PdfMerge/LICENSE
14 | icon.ico
15 | https://github.com/Structed/PdfMerge
16 | Structed.me
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/PdfMerge/Program.cs:
--------------------------------------------------------------------------------
1 | using PdfSharp.Pdf;
2 | using PdfSharp.Pdf.IO;
3 |
4 | namespace PdfMerge
5 | {
6 | class Program
7 | {
8 | static void Main(string[] args)
9 | {
10 | if (args.Length < 2)
11 | {
12 | Console.WriteLine("Please provide at least one PDF file path.");
13 | return;
14 | }
15 |
16 | string outputFilePath = "mergePdf.pdf";
17 | using (PdfDocument outputDocument = new PdfDocument())
18 | {
19 | foreach (string filePath in args)
20 | {
21 | if (File.Exists(filePath) && Path.GetExtension(filePath).Equals(".pdf", StringComparison.OrdinalIgnoreCase))
22 | {
23 | PdfDocument inputDocument = PdfReader.Open(filePath, PdfDocumentOpenMode.Import);
24 | for (int i = 0; i < inputDocument.PageCount; i++)
25 | {
26 | PdfPage page = inputDocument.Pages[i];
27 | outputDocument.AddPage(page);
28 | }
29 | }
30 | else
31 | {
32 | Console.WriteLine($"File not found or not a PDF: {filePath}");
33 | }
34 | }
35 |
36 | outputDocument.Save(outputFilePath);
37 | Console.WriteLine($"Merged PDF saved as {outputFilePath}");
38 | }
39 | }
40 | }
41 | }
--------------------------------------------------------------------------------
/PdfMerge/icon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Structed/PdfMerge/ac1f47a7004f74622d1075b7200c44f12c11c492/PdfMerge/icon.ico
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | 
2 |
3 | A super simple CLI tool to merge PDFs.
4 |
5 | Get the Win x64 binary here: https://github.com/Structed/PdfMerge/releases/tag/1.0
6 |
7 |
8 | ## Usage
9 | Just run the tool and add 2 or more PDF file paths as arguments to merge them. Pages will be read in this order and appended to a new `mergePdf.pdf` file in the same directory.
10 | `pdfmerge "c:\pdf1.pdf" "c:\pdf2.pdf" "c:\pdf3.pdf"`
11 |
--------------------------------------------------------------------------------
/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Structed/PdfMerge/ac1f47a7004f74622d1075b7200c44f12c11c492/icon.png
--------------------------------------------------------------------------------