2%APPEND_PDFS Appends/concatenates multiple PDF files
5%
append_pdfs(outputFilename, inputFilename1, inputFilename2, ...)
7%
append_pdfs(outputFilename, inputFilenames_cell_or_string_array)
10% This function appends multiple PDF files to an existing PDF file, or
11% concatenates them into a PDF file
if the output file doesn
't yet exist.
13% This function requires that you have ghostscript installed on your
14% system. Ghostscript can be downloaded from: http://www.ghostscript.com
17% output - output file name (including the .pdf extension).
18% If it exists it is appended to; if not, it is created.
19% input1 - input file name(s) (including the .pdf extension).
20% All input files are appended in order.
21% input_list - cell array list of input file name strings. All input
22% files are appended in order.
24% Copyright: Oliver Woodford, 2011-2014, Yair Altman 2015-
27% Thanks to Reinhard Knoll for pointing out that appending multiple pdfs in
28% one go is much faster than appending them one at a time.
30% Thanks to Michael Teo for reporting the issue of a too long command line.
31% Issue resolved on 5/5/2011, by passing gs a command file.
33% Thanks to Martin Wittmann for pointing out quality issue when appending bitmaps
34% Issue resolved (to best of my ability) 1/6/2011, using the prepress setting
36% 26/02/15: If temp dir is not writable, use the output folder for temp
37% files when appending (Javier Paredes); sanity check of inputs
38% 24/01/18: Fixed error in case of existing output file (append mode)
39% 24/01/18: Fixed issue #213: non-ASCII characters in folder names on Windows
40% 06/12/18: Avoid an "invalid escape-char" warning upon error
41% 22/03/20: Alert if ghostscript.m is not found on Matlab path
42% 29/03/20: Accept a cell-array of input files (issue #299); accept both "strings", 'chars
'
43% 25/01/22: Improved handling of missing input files & folder with non-ASCII chars (issue #349)
44% 07/06/23: Fixed (hopefully) unterminated quote run-time error (issues #367, #378); fixed handling of pathnames with non-ASCII chars (issue #349); display ghostscript command upon run-time invocation error
45% 06/07/23: Another attempt to fix issue #378 (remove unnecessary quotes from ghostscript cmdfile)
48 if nargin < 2, return; end % sanity check
50 % Convert strings => chars; strtrim extra spaces
51 varargin = cellfun(@str2char,varargin,'un
',false);
53 % Convert cell array into individual strings (issue #299)
54 if nargin==2 && iscell(varargin{2})
55 varargin = {varargin{1} varargin{2}{:}}; %#ok<CCAT>
58 % Handle special cases of input args
59 numArgs = numel(varargin);
64 % Ensure that ghostscript() exists on the Matlab path
69 % Are we appending or creating a new file?
70 append = exist(varargin{1}, 'file') == 2;
71 if ~append && numArgs == 2 % only 1 input file -
copy it directly to output
72 copyfile(varargin{2}, varargin{1});
76 % Ensure that the temp dir is writable (Javier Paredes 26/2/15)
77 output = [tempname '.pdf'];
79 fid = fopen(output,'w');
85 % Temp dir is not writable, so use the output folder
86 [dummy,fname,fext] = fileparts(output); %
#ok<ASGLU>
87 fpath = fileparts(varargin{1});
88 output = fullfile(fpath,[fname fext]);
93 varargin = varargin(2:end);
96 % Ensure that all input files exist
97 for fileIdx = 2 : numel(varargin)
98 filename = varargin{fileIdx};
99 if ~exist(filename,
'file')
100 error('export_fig:append_pdf:MissingFile','Input file %s does not exist',filename);
104 % Create the command file
106 cmdfile = [tempname '.txt'];
108 cmdfile = fullfile(fpath,[fname '.txt']);
111 hCleanup = onCleanup(@()
cleanup(cmdfile));
114 [status, errMsg] =
ghostscript([
'@"' cmdfile
'"']);
117 if status && ~isempty(strfind(errMsg,
'undefinedfile')) && ispc %#ok<STREMP>
118 % Fix issue #213: non-ASCII characters in folder names on Windows
119 for fileIdx = 2 : numel(varargin)
120 [fpath,fname,fext] = fileparts(varargin{fileIdx});
121 varargin{fileIdx} = fullfile(
normalizePath(fpath),[fname fext]);
123 % Rerun
ghostscript with the normalized folder names
125 [status, errMsg] =
ghostscript([
'@"' cmdfile
'"']);
128 % Delete the command file
134 errMsg = strrep(errMsg,
'\',
'\\'); % Avoid an
"invalid escape-char" warning
135 error(
'export_fig:append_pdf:ghostscriptError',errMsg);
138 % Rename the file
if needed
140 movefile(output, varargin{1},
'f');
146 % Delete the command file
147 try delete(cmdfile);
catch, end
152 if ispc, output(output==
'\') =
'/'; varargin = strrep(varargin,
'\',
'/'); end
153 varargin = strrep(varargin,
'"',
'');
155 str = [
'-q -dNOPAUSE -dBATCH -sDEVICE=pdfwrite -dPDFSETTINGS=/prepress ' ...
156 '-sOutputFile="' output
'" -f ' sprintf(
'"%s" ',varargin{:})];
157 str = regexprep(str,
' "?" ',
' '); % remove empty strings (issues #367,#378)
158 str = regexprep(str, '"([^ ]*)"', '$1'); % remove unnecessary quotes
159 str = strtrim(str); % trim extra spaces
161 fh = fopen(cmdfile, 'w');
162 fprintf(fh,'%s',str);
166% Convert
long/non-ASCII folder names into their
short ASCII equivalents
168 [fpath,fname,fext] = fileparts(pathStr);
169 if isempty(fpath) || strcmpi(fpath,pathStr), return, end
170 dirOutput = evalc(['system(''dir /X /AD "' pathStr '*"'')']);
171 regexpStr = ['.*\s(\S+)\s*' fname fext '.*'];
172 shortName = regexprep(dirOutput,regexpStr,'$1');
173 if isempty(shortName) || isequal(shortName,dirOutput) || strcmpi(shortName,'<DIR>')
174 shortName = [fname fext];
176 fpath =
normalizePath(fpath); %recursive until entire fpath is processed
177 pathStr = fullfile(fpath, shortName);
180% Convert a possible
string =>
char
183 value = controllib.internal.util.hString2Char(value);
185 if isa(value,'
string')
189 value = strtrim(value);
function normalizePath(in pathStr)
function prepareCmdFile(in cmdfile, in output, in varargin)
function str2char(in value)
function append_pdfs(in varargin)
function cleanup(in cmdfile)
function copy(in from, in to, in field, in exclude)
Copy the contents of the struct/object from to the struct/object to recursively and without destroyin...
function ghostscript(in cmd)