############################################################################
#
# File: gdl2.icn
#
# Subject: Procedures to get directory lists
#
# Authors: Richard L. Goerwitz and Charles Shartsis
#
# Date: August 14, 1995
#
############################################################################
#
# This file is in the public domain.
#
############################################################################
#
# Version: 1.3+
#
############################################################################
#
# Gdl returns a list containing everything in a directory (whose name
# must be passed as an argument to gdl). Nothing fancy. I use this file
# as a template, modifying the procedures according to the needs of the
# program in which they are used.
#
# NOTE: MSDOS results are all in lower case
#
# Modifications:
# 1) Fixed MSDOS routines.
# 2) Added gdlrec which does same thing as gdl except it recursively descends
# through subdirectories. May choose which Unix utility to use by passing
# in method parameter. See below.
#
############################################################################
#
# Requires: UNIX or MS-DOS
#
############################################################################
procedure gdl(dir)
local getdir
getdir := set_getdir_by_os()
return getdir(dir)
end
procedure gdlrec(dir, method)
# Unix method to use: &null for compatibility (uses "/bin/ls"),
# not null for speed (uses "find")
local getdir
getdir := set_getdir_rec_by_os(method)
return getdir(dir)
end
procedure set_getdir_by_os()
# Decide how to get a directory, based on whether we are running
# under Unix or MS-DOS.
if find("UNIX", &features)
then return unix_get_dir
else if find("MS-DOS", &features)
then return msdos_get_dir
else stop("Your operating system is not (yet) supported.")
end
procedure set_getdir_rec_by_os(method)
# Decide how to get a directory, based on whether we are running
# under Unix or MS-DOS.
if find("UNIX", &features) then {
if /method then
return unix_get_dir_rec
else
return unix_get_dir_rec2
}
else if find("MS-DOS", &features) then
return msdos_get_dir_rec
else
stop("Your operating system is not (yet) supported.")
end
procedure msdos_get_dir(dir)
# Returns a sorted list of all filenames (full paths included) in
# directory "dir." The list is sorted. Fails on invalid or empty
# directory. Aborts if temp file cannot be opened.
#
# Temp files can be directed to one or another directory either by
# manually setting the variable temp_dir below, or by setting the
# value of the environment variable TEMPDIR to an appropriate
# directory name.
local in_dir, filename_list, line, temp_name, filename
static temp_dir
initial {
temp_dir :=
(trim(map(getenv("TEMPDIR"), "/", "\\"), '\\') || "\\") |
".\\"
}
# Get name of tempfile to be used.
temp_name := get_dos_tempname(temp_dir) |
stop("No more available tempfile names!")
### Added by C. Shartsis 9/19/94
# Make implicit current directory explicit
# Otherwise current and root directory get mapped to same thing
if (dir == "") |
(dir ? (tab(any(&letters)) & =":" & pos(0)) )
then
dir ||:= "."
# Make sure we have an unambiguous directory name, with backslashes
# instead of Unix-like forward slashes.
dir := trim(map(dir, "/", "\\"), '\\')
### Added by C. Shartsis 9/19/94
# Put backslash back on if dir is the root directory
# Otherwise the current directory is returned
if (dir == "") |
(dir ? (tab(any(&letters)) & =":" & pos(0)) )
then
dir ||:= "\\"
# Put dir listing into a temp file.
system("dir "||dir||" > "||temp_name)
# Put tempfile entries into a list, removing blank- and
# space-initial lines. Exclude directories (i.e. return file
# names only).
in_dir := open(temp_name,"r") |
stop("Can't open temp file in directory ",temp_dir,".")
filename_list := list()
every filename := ("" ~== !in_dir) do {
match(" ",filename) | find("
", filename) & next
# Exclude our own tempfiles (may not always be appropriate).
filename ?:= trim(trim(tab(10)) || "." || tab(13), '. ')
### Change: C. Shartsis - 4/9/95
# Exclude tempfile
if filename ? (
="ICONDIR." & tab(any(&digits)) & tab(any(&digits)) & tab(any(&digits))
) then
next
### Change: C. Shartsis - 9/19/94
# Otherwise file f in directory c:\d comes out as "c:\df" instead of "c:\d\f"
#put(filename_list, map(dir || filename))
put(filename_list, map(trim(dir, '\\') || "\\" || filename))
}
# Clean up.
close(in_dir) & remove(temp_name)
# Check to be sure we actually managed to read some files.
if *filename_list = 0 then fail
else return sort(filename_list)
end
procedure msdos_get_dir_rec(dir, level)
# Returns a sorted list of all filenames (full paths included) in
# directory "dir." The list is sorted. Fails on invalid or empty
# directory. Aborts if temp file cannot be opened.
#
# Temp files can be directed to one or another directory either by
# manually setting the variable temp_dir below, or by setting the
# value of the environment variable TEMPDIR to an appropriate
# directory name.
local in_dir, line, filename, raw_list
local tmp_filelist, tmp_dirlist
static temp_dir, temp_name, filename_list
initial {
temp_dir :=
(trim(map(getenv("TEMPDIR"), "/", "\\"), '\\') || "\\") |
".\\"
}
# Establish recursion level
/level := 0
if level = 0 then {
filename_list := list()
# Get name of tempfile to be used.
temp_name := get_dos_tempname(temp_dir) |
stop("No more available tempfile names!")
}
# Make implicit current directory explicit
# Otherwise current and root directory get mapped to same thing
if (dir == "") |
(dir ? (tab(any(&letters)) & =":" & pos(0)) )
then
dir ||:= "."
# Make sure we have an unambiguous directory name, with backslashes
# instead of Unix-like forward slashes.
dir := trim(map(dir, "/", "\\"), '\\')
# Put backslash back on if dir is the root directory
# Otherwise the current directory is returned
if (dir == "") |
(dir ? (tab(any(&letters)) & =":" & pos(0)) )
then
dir ||:= "\\"
# Put dir listing into a temp file.
system("dir "||dir||" > "||temp_name)
# Put tempfile entries into a list, removing blank- and
# space-initial lines. Exclude directories (i.e. return file
# names only).
in_dir := open(temp_name,"r") |
stop("Can't open temp file in directory ",temp_dir,".")
raw_list := []
every put(raw_list, !in_dir)
# Clean up.
close(in_dir) & remove(temp_name)
tmp_dirlist := []
tmp_filelist := []
every filename := ("" ~== !raw_list) do {
match(" ",filename) | match(".",filename) & next
# Process Directories
if find(" ", filename) then {
filename ?:= tab(many(~' \t'))
put(tmp_dirlist, map(trim(dir, '\\') || "\\" || filename))
}
# Save files to list
else {
# extract the file name
filename ?:= trim(trim(tab(10)) || "." || tab(13), '. ')
# Exclude tempfile
if not (filename ? (
="ICONDIR." & tab(any(&digits)) & tab(any(&digits)) & tab(any(&digits))
)) then
# Otherwise file f in directory c:\d comes out as "c:\df" instead of "c:\d\f"
put(tmp_filelist, map(trim(dir, '\\') || "\\" || filename))
}
}
# Add files to master list
every put(filename_list, !sort(tmp_filelist))
# Process remaining directories
every msdos_get_dir_rec(!sort(tmp_dirlist), level + 1)
# Check to be sure we actually managed to read some files.
if level = 0 then {
if *filename_list = 0 then fail
else return filename_list
}
end
procedure get_dos_tempname(dir)
local temp_name, temp_file
# Don't clobber existing files. Get a unique temp file name for
# use as a temporary storage site.
every temp_name := dir || "icondir." || right(string(1 to 999),3,"0") do {
temp_file := open(temp_name,"r") | break
close(temp_file)
}
return \temp_name
end
procedure unix_get_dir(dir)
local filename_list, in_dir, filename
dir := trim(dir, '/') || "/"
filename_list := list()
in_dir := open("/bin/ls -F "||dir, "pr")
every filename := ("" ~== !in_dir) do {
match("/",filename,*filename) & next
put(filename_list, trim(dir || filename, '*'))
}
close(in_dir)
if *filename_list = 0 then fail
else return filename_list
end
procedure unix_get_dir_rec(dir, level)
# Returns a sorted list of all filenames (full paths included) in
# directory "dir." The list is sorted. Fails on invalid or empty
# directory. Aborts if temp file cannot be opened.
local in_dir, filename, raw_list, cmd
local tmp_filelist, tmp_dirlist
static filename_list
# Establish recursion level
/level := 0
if level = 0 then
filename_list := list()
# Append trailing slash
dir := trim(dir, '/') || "/"
# Put tempfile entries into a list, removing blank- and
# space-initial lines. Exclude directories (i.e. return file
# names only).
cmd := "/bin/ls -FL " || dir
in_dir := open(cmd,"pr") |
stop(cmd, " will not run on this system")
raw_list := []
every put(raw_list, !in_dir)
# Clean up.
close(in_dir)
tmp_dirlist := []
tmp_filelist := []
every filename := ("" ~== !raw_list) do {
if match(" ",filename) | match(".",filename) | filename[-1] == "=" then
next
if filename[-1] == "*" then
filename := filename[1:-1]
# Process Directories
if filename[-1] == "/" then
put(tmp_dirlist, dir || filename)
# Save files to list
else
put(tmp_filelist, dir || filename)
}
# Add files to master list
every put(filename_list, !sort(tmp_filelist))
# Process remaining directories
every unix_get_dir_rec(!sort(tmp_dirlist), level + 1)
# Check to be sure we actually managed to read some files.
if level = 0 then {
if *filename_list = 0 then fail
else return filename_list
}
end
# This works too.
# This routine is faster but depends on the Unix "find" program.
# Don't know if all Unixes have this.
procedure unix_get_dir_rec2(dir)
local filename_list, in_dir, cmd
dir := trim(dir, '/') || "/"
filename_list := list()
cmd := "find " || dir || " -type f -print"
in_dir := open(cmd, "pr") |
stop(cmd, " will not run on this system")
every put(filename_list, !in_dir)
close(in_dir)
if *filename_list = 0 then fail
else return filename_list
end