Now it is possible to write a small Lisp program callable from the command line on Windows. Allegro CL 8.0 and a patch are required to use the facility described here. Scripting on UNIX is described here.
To illustrate this feature, we present an example. This script is used to rename files which are the result of scanning photos. After scanning, the files are given descriptive names like cat-on-roof.jpg. After a large number of files are scanned, they are sorted into directories whose names contain the dates, sometimes approximate, when the pictures were taken. After the sorting, the task is to rename the files, again, so that their names contain the date. In other words:
The details of the program,
scanprefix.cl
(view or
download),
are not important.
What is important is how we package it for use.
We will use a new Allegro CL function,
excl:lisp-to-bat-file
,
to create a .bat file from a .cl file.
This .bat file can then be run from the Windows command shell
(cmd.exe):
(excl:lisp-to-bat-file "scanprefix.cl" ; source file "scanprefix.bat" ; output file :executable "sys:build" ; Lisp executable to use (more below) :image "sys:mlisp8.dxl" :pause nil ; whether to pause at end (more below) :if-exists :supersede ; whether to supersede the output file )
scanprefix.bat looks like this:
@echo off "c:\Program Files\acl80\build" -I "c:\Program Files\acl80\mlisp8.dxl" --bat "c:\bin\scanprefix.bat" -- %* goto xxx_l2b_end ;;NEED THIS COMMENT TO DELINEATE THE LISP CODE ...contents of scanprefix.cl removed for brevity... :end-of-script :xxx_l2b_end
In this case, a console app was chosen, instead of a Windows app. The difference is the output a console generates goes to the cmd.exe window, and the output from a Windows program goes into an application-specific window. See the Table of compatibible predefined images for more information. For example, from the table, the combination of build.exe and mlisp.dxl is not allowed. Not allowed means this command would fail:
c:\>"c:\Program Files\acl80\build.exe" -I mlisp.dxl Error: The lisp executable and image file differ as to the use of the international character set Could not restore the image file: c:\Program Files\acl80\mlisp.dxl. c:\>
If we wanted to make a windows app, we could do it this way:
(excl:lisp-to-bat-file "scanprefix.cl" ; source file "scanprefix.bat" ; output file :executable "sys:mlisp" ; Lisp executable to use :image "sys:mlisp.dxl" :pause t ; whether to pause at end :if-exists :supersede ; whether to supersede the output file )Notice that we changed not only the
:executable
and
:image
keyword values, but also changed the
:pause
value to
t
.
Now, that we have made scanprefix.bat, we just need to put it in some directory in our PATH environment variable. Otherwise, we will need to fully qualify the path to the script. We can use it like this:
c:\>scanprefix Usage: scanprefix [-x] directory -x - do the renames, otherwise just print what would be done directory - the directory to scan for .jpg's c:\>or
c:\>scanprefix c:/pictures/_TMP/scans c:\pictures\_TMP\scans\1995-01-25\1994-12-24-vu-xmas\: 1995-01-25-anh-parents.jpg => 1994-12-24-anh-parents.jpg 1995-01-25-anh-parents2.jpg => 1994-12-24-anh-parents2.jpg 1995-01-25-anh.jpg => 1994-12-24-anh.jpg 1995-01-25-linda.jpg => 1994-12-24-linda.jpg 1995-01-25-linda2.jpg => 1994-12-24-linda2.jpg 1995-01-25-manh.jpg => 1994-12-24-manh.jpg 1995-01-25-ngan.jpg => 1994-12-24-ngan.jpg anh-parents3.jpg => 1994-12-24-anh-parents3.jpg blind-wrap-done.jpg => 1994-12-24-blind-wrap-done.jpg blind-wrap.jpg => 1994-12-24-blind-wrap.jpg linda3.jpg => 1994-12-24-linda3.jpg manh.jpg => 1994-12-24-manh.jpg mickey-ngan2.jpg => 1994-12-24-mickey-ngan2.jpg mickey-ngan3.jpg => 1994-12-24-mickey-ngan3.jpg c:\pictures\_TMP\scans\1995-01-25\1994-franz\: ethan.jpg => 1994-ethan.jpg hackysack.jpg => 1994-hackysack.jpg sara.jpg => 1994-sara.jpg c:\pictures\_TMP\scans\1995-01-25\1995-misc\: alan.jpg => 1995-alan.jpg anh-alan.jpg => 1995-anh-alan.jpg anh3.jpg => 1995-anh3.jpg kevin-alan.jpg => 1995-kevin-alan.jpg You can rename the above files by executing: scanprefix -x c:/pictures/_TMP/scans c:\>scanprefix -x c:/pictures/_TMP/scans c:\pictures\_TMP\scans\1995-01-25\1994-12-24-vu-xmas\: renamed: 1995-01-25-anh-parents.jpg => 1994-12-24-anh-parents.jpg renamed: 1995-01-25-anh-parents2.jpg => 1994-12-24-anh-parents2.jpg renamed: 1995-01-25-anh.jpg => 1994-12-24-anh.jpg renamed: 1995-01-25-linda.jpg => 1994-12-24-linda.jpg renamed: 1995-01-25-linda2.jpg => 1994-12-24-linda2.jpg renamed: 1995-01-25-manh.jpg => 1994-12-24-manh.jpg renamed: 1995-01-25-ngan.jpg => 1994-12-24-ngan.jpg renamed: anh-parents3.jpg => 1994-12-24-anh-parents3.jpg renamed: anh.jpg => 1994-12-24-anh.jpg renamed: blind-wrap-done.jpg => 1994-12-24-blind-wrap-done.jpg renamed: blind-wrap.jpg => 1994-12-24-blind-wrap.jpg renamed: linda3.jpg => 1994-12-24-linda3.jpg renamed: manh.jpg => 1994-12-24-manh.jpg renamed: mickey-ngan2.jpg => 1994-12-24-mickey-ngan2.jpg renamed: mickey-ngan3.jpg => 1994-12-24-mickey-ngan3.jpg c:\pictures\_TMP\scans\1995-01-25\1995-misc\: renamed: alan.jpg => 1995-alan.jpg renamed: anh-alan.jpg => 1995-anh-alan.jpg renamed: anh3.jpg => 1995-anh3.jpg renamed: kevin-alan.jpg => 1995-kevin-alan.jpg Renamed 19 files. c:\>
Another example using the -s argument to the script, also calling the script from BASH (you must use the full name of the script, including the .bat suffix):
bash$ scanprefix.bat c:/pictures/_TMP/scans c:\pictures\_TMP\scans\1987-08-kentucky\: anh.jpg => 1987-08-anh.jpg anh-doris.jpg => 1987-08-anh-doris.jpg anh2.jpg => 1987-08-anh2.jpg andy-doris2.jpg => 1987-08-andy-doris2.jpg dog.jpg => 1987-08-dog.jpg andy-doris.jpg => 1987-08-andy-doris.jpg horses.jpg => 1987-08-horses.jpg horses2.jpg => 1987-08-horses2.jpg anh-reservoir.jpg => 1987-08-anh-reservoir.jpg country.jpg => 1987-08-country.jpg anh-doris2.jpg => 1987-08-anh-doris2.jpg anh-reservoir2.jpg => 1987-08-anh-reservoir2.jpg castle.jpg => 1987-08-castle.jpg andy.jpg => 1987-08-andy.jpg anh-wink.jpg => 1987-08-anh-wink.jpg You can rename the above files by executing: scanprefix -x c:/pictures/_TMP/scans bash$ scanprefix.bat -x c:/pictures/_TMP/scans c:\pictures\_TMP\scans\1987-08-kentucky\: renamed: anh.jpg => 1987-08-anh.jpg renamed: anh-doris.jpg => 1987-08-anh-doris.jpg renamed: anh2.jpg => 1987-08-anh2.jpg renamed: andy-doris2.jpg => 1987-08-andy-doris2.jpg renamed: dog.jpg => 1987-08-dog.jpg renamed: andy-doris.jpg => 1987-08-andy-doris.jpg renamed: horses.jpg => 1987-08-horses.jpg renamed: horses2.jpg => 1987-08-horses2.jpg renamed: anh-reservoir.jpg => 1987-08-anh-reservoir.jpg renamed: country.jpg => 1987-08-country.jpg renamed: anh-doris2.jpg => 1987-08-anh-doris2.jpg renamed: anh-reservoir2.jpg => 1987-08-anh-reservoir2.jpg renamed: castle.jpg => 1987-08-castle.jpg renamed: andy.jpg => 1987-08-andy.jpg renamed: anh-wink.jpg => 1987-08-anh-wink.jpg Renamed 15 files.
For those interested in automating the creation of the scripts from source files, below is a GNU make makefile that does the work. GNU make can be installed on Windows from cygwin.com. Put this in a file called makefile:
# Makefile to turn lisp files into bat files, so they can be run from a DOS # prompt (ie, in a cmd.exe). # Kevin Layer, Jan 2006. # # Requirements: # 1. Allegro CL 8.0, with patch aclstart.001 and startup.001. # 2. GNU make acldir = c:/Program Files/acl80 scripts = scanprefix.bat default: $(scripts) %.bat: %.cl makefile @rm -f build.tmp echo '(setq excl::*break-on-warnings* t)' >> build.tmp #### The compilation is both a validation and creates a .fasl file which #### can be used directly. echo '(compile-file "$*.cl")' >> build.tmp echo '(excl:lisp-to-bat-file "$*.cl" "$*.bat" ' >> build.tmp #### Choose one: #### the first uses a Windows console app, where the output #### goes to the cmd.exe window where the script is run #### the second a typical Windows app where the output goes #### into its own Window. The `pause' is needed for this #### case because the output of the script will not be seen #### unless there is a pause. Of course, if you don't want #### to see the output of the script, you leave :pause as nil. echo ' :executable "sys:build" ' >> build.tmp echo ' :pause nil ' >> build.tmp # echo ' :executable "sys:mlisp8" ' >> build.tmp # echo ' :pause t ' >> build.tmp #### echo ' :image "sys:mlisp8.dxl" ' >> build.tmp echo ' :if-exists :supersede ' >> build.tmp echo ')' >> build.tmp echo '(exit 0)' >> build.tmp sh "$(acldir)/src/runlisp.sh" -f build.tmp mlisp # remove if the previous command succeeded @rm -f runlisp.out @rm -f build.tmp clean: FORCE rm -f $(scripts) build.tmp runlisp.out FORCE:
All that is necessary to add a new script is to add it to the scripts line in the makefile and then to execute make in the directory that contains the makefile and the Lisp source files.
bash$ make echo '(setq excl::*break-on-warnings* t)' >> build.tmp echo '(compile-file "scanprefix.cl")' >> build.tmp echo '(excl::lisp-to-bat-file "scanprefix.cl" "scanprefix.bat" ' >> build.tmp echo ' :executable "sys:build" ' >> build.tmp echo ' :pause nil ' >> build.tmp echo ' :image "sys:mlisp8.dxl" ' >> build.tmp echo ' :if-exists :supersede ' >> build.tmp echo ')' >> build.tmp echo '(exit 0)' >> build.tmp sh "c:/Program Files/acl80/src/runlisp.sh" -f build.tmp mlisp mlisp +M +B +cn +s build.tmp -q -batch -backtrace-on-error -d runlisp.out [lisp output redirected to runlisp.out] bash$
NOTE:
Because of some fiddling with *features*
in the script,
you can also load the fasl file associated with the script without
having it execute code based on the command line arguments to the Lisp
you load it into. That means you could do something like this:
cl-user(1): :ld c:/bin/scanprefix.fasl ... cl-user(2): (scan-root "c:/pictures/_TMP/scans/") ...
Copyright © Franz Inc., All Rights Reserved | Privacy Statement |