From: Kendall Gifford Date: 2012-04-28T03:36:05+09:00 Subject: Re: Can you speed this up? --e89a8f2357e3873cc304bead5c1b Content-Type: text/plain; charset=UTF-8 On Fri, Apr 27, 2012 at 12:04 PM, Christopher D. wrote: > I often use ruby to run through one set of files and then look at > another and if they match then I delete a file, append them.. whatever. > I'm relatively new to ruby so I always want to improve the efficiency of > my code. Here is working code that I used to append two files in > seperate folders and place them in a finalpost folder. > > How could I improve my code? > > Temphome = Dir["P:/project/post/Temphome/*.pdf"] > Temprep = Dir["P:/project/post/Temprep/*.pdf"] > > Temphome.each do |filetemp| > Temprep.each do |filerep| > filerep = File.basename(filerep) > filetemp = File.basename(filetemp) > if filerep == filetemp > cmd = "P:\\project\\bin\\pdftk.exe > P:\\project\\post\\Temphome\\#{filetemp} > P:\\project\\post\\Temprep\\#{filetemp} cat output > P:\\project\\post\\Finaltal\\#{filetemp}" > puts "Appending #{filetemp}" > `#{cmd}` > else next > end > end > end > > puts "Finished Appending, the new files are located in > P:\\project\\post\\finalpost" > > I don't think this is likely to be faster, but it is a slightly different approach: 1 #!/usr/bin/env ruby 2 # encoding: utf-8 3 4 require 'shellwords' 5 6 HOME = File.join %w{ P: project post Temphome } 7 PREP = File.join %w{ P: project post Tempprep } 8 DEST = File.join %w{ P: project post Finaltal } 9 TOOL = File.join %w{ P: project bin pdftk.exe } 10 11 Dir[File.join(HOME, '*.pdf')].each do |temp| 12 name = File.basename(temp) 13 prep = File.join(PREP, name) 14 if File.exists?(prep) 15 command = [TOOL, temp, prep, 'cat', 'output', File.join(DEST, name)].shelljoin 16 puts "Appending #{name}" 17 `#{command}` 18 end 19 end Instead of looping twice (for n * m iterations) this just iterates once over the first collection of files (n iterations), a theoretical "big-O" improvement. However, I suspect that *if* there's any performance gain from this, that it's easily overshadowed by the overhead of running "pdftk" to concat PDFs. However, though there's likely no performance improvements, this does demonstrate the cool "shellwords" library (part of the standard library: http://www.ruby-doc.org/stdlib-1.9.2/libdoc/shellwords/rdoc/index.html ). It is usually much safer to use shellwords to construct commands you plan to execute as it'll take care of quoting (and escaping characters) in filenames/commands in case you have spaces in a filename or command token (or other characters that need quoting or escaping). (NOTE: I'm *assuming* shellwords is fully customized to work appropriately for the windows command shell...) I've also used the "cross-platform" technique of "File.join(...)" which uses the correct path separator for your platform (backslashes for windows). However, it appears from your working code that ruby must internally transform forward-slashes to backslashes in paths on windows (in at least some places) but it's probably still a good idea to use "File.join(...)". -- Kendall Gifford zettabyte@gmail.com --e89a8f2357e3873cc304bead5c1b Content-Type: text/html; charset=UTF-8 Content-Transfer-Encoding: quoted-printable
On Fri, Apr 27, 2012 at 12:04 PM, Christopher D.= <lists@ruby-forum.com> wrote:
I often use ruby to run through one set of files and then look at
another and if they match then I delete a file, append them.. whatever.
I'm relatively new to ruby so I always want to improve the efficiency o= f
my code. Here is working code that I used to append two files in
seperate folders and place them in a finalpost folder.

How could I improve my code?

Temphome =3D Dir["P:/project/post/Temphome/*.pdf"]
Temprep =3D Dir["P:/project/post/Temprep/*.pdf"]

=C2=A0Temphome.each do |filetemp|
=C2=A0 =C2=A0Temprep.each do |filerep|
=C2=A0 =C2=A0 =C2=A0filerep =3D File.basename(filerep)
=C2=A0 =C2=A0 =C2=A0filetemp =3D File.basename(filetemp)
=C2=A0 =C2=A0 =C2=A0if filerep =3D=3D filetemp
=C2=A0 =C2=A0 =C2=A0 =C2=A0cmd =3D "P:\\project\\bin\\pdftk.exe
P:\\project\\post\\Temphome\\#{filetemp}
P:\\project\\post\\Temprep\\#{filetemp} cat output
P:\\project\\post\\Finaltal\\#{filetemp}"
=C2=A0 =C2=A0 =C2=A0 =C2=A0puts "Appending #{filetemp}"
=C2=A0 =C2=A0 =C2=A0 =C2=A0`#{cmd}`
=C2=A0 =C2=A0 =C2=A0else next
=C2=A0 =C2=A0 =C2=A0end
=C2=A0 =C2=A0end
=C2=A0end

=C2=A0puts "Finished Appending, the new files are located in
P:\\project\\post\\finalpost"

=

I don't think this is likely to be faster, but it is a slight= ly different approach:

=C2=A0 1 #!/usr/bin/env ruby
=C2=A0 2 # encoding: utf-= 8
=C2=A0 3
=C2=A0 4 require 'she= llwords'
=C2=A0 5
=C2=A0 6 HOME =3D File.jo= in %w{ P: project post Temphome }
=C2=A0 7 PRE= P =3D File.join %w{ P: project post Tempprep }
=C2=A0 8 DEST =3D File.jo= in %w{ P: project post Finaltal }
=C2=A0 9 TOO= L =3D File.join %w{ P: project bin=C2=A0 pdftk.exe }
=C2=A010
=C2=A011 Dir[File.join(HOME, '*.pdf')].each do |temp|=
=C2=A012=C2=A0=C2=A0 name= =3D File.basename(temp)
=C2=A013=C2=A0=C2=A0 = prep =3D File.join(PREP, name)
=C2=A014=C2=A0=C2=A0 if F= ile.exists?(prep)
=C2=A015=C2=A0=C2=A0=C2=A0= =C2=A0 command =3D [TOOL, temp, prep, 'cat', 'output', File= .join(DEST, name)].shelljoin
=C2=A016=C2=A0=C2=A0=C2= =A0=C2=A0 puts "Appending #{name}"
= =C2=A017=C2=A0=C2=A0=C2=A0=C2=A0 `#{command}`
=C2=A018=C2=A0=C2=A0 end<= /span>
=C2=A019 end

Instead of looping = twice (for n * m i= terations) this just iterates once over the first collection of files (n
iterations), a theor= etical "big-O" improvement. However, I suspect that *if* there= 9;s any performance gain from this, that it's easily overshadowed by th= e overhead of running "pdftk" to concat PDFs.

However, though there's likely no performance improvements, this do= es demonstrate the cool "shellwords" library (part of the standar= d library: http://www.ruby-doc.org/stdlib-1.9.2/libdoc/shellwords/r= doc/index.html ). It is usually much safer to use shellwords to constru= ct commands you plan to execute as it'll take care of quoting (and esca= ping characters) in filenames/commands in case you have spaces in a filenam= e or command token (or other characters that need quoting or escaping). (NO= TE: I'm *assuming* shellwords is fully customized to work appropriately= for the windows command shell...)

I've also used the "cross-platform" technique of "File.join(...)"= which uses the correct path separator for your platform (backslashes for w= indows). However, it appears from your working code that ruby must internal= ly transform forward-slashes to backslashes in paths on windows (in at leas= t some places) but it's probably still a good idea to use "File.jo= in(...)".

--
Kendall Gifford
zettabyte@gmail.com
--e89a8f2357e3873cc304bead5c1b--