FilesAndDirs (Class)
Overview
This class offers methods useful to deal with files and directories. The class attempts to be platform independent: it should work under Windows, Linux and Mac-OS.
With the release of 15.0 Dyalog introduced some new ⎕n
-system functions that are helpful for making an application platform independent when it comes to files and directories.
However, those new functions do not fully cover the frequent need of applications. Examples include functionalities like “Move”, “Copy” and recursive listings of directories. This class attempts to fill this gap.
Note that error codes as well as messages for the same kind of problem may differ between operating systems.
Slashes and backslashes in file- and directory names
Note that all \
are changed to /
. This is done by the NormalizePath
method. It seems to be a natural thing to do but it has a drawback: you cannot deal with files and directories under Linux or Mac OS that have a \
in their names - the backslash is potentially a character that is part of a filename under those operating systems.
However, if you attempt to produce platform independent code then you must not use the backslash characters as part of filenames anyway. The main thing to keep in mind is then that you should always make sure that you normalize file- and directory names because if you don't then you are likely to create a direcotry or file that carries a backslash in its name alhtough you did not intend to this at all!
This is also the reason why there are some function that have native aquivalents like DeleteFile
, Exists
, CreateFile
and MkDir
: by using them you make sure that you won't forgot to normalize any filenames or directory names because the functions do this for you.
Misc
This class supports Windows, Mac OS and Linux but neither the PI nor AIX. Kai Jaeger ⋄ APL Team Ltd
Homepage: http://aplwiki.com/FilesAndDirs
Version
Version 1.1.1 from 2016-09-01
Reference
Included
- APLTreeUtils
Shared Methods
Cd
Syntax:
r ← Cd pathReports and/or changes the current directory. The method changes the current directory to what the right argument is ruling.
It returns the former current directory as a result.
Because an empty right argument has no effect, Cd ''
effectively reports the current directory.
See also PWD
(Print Work Directory).
CheckPath
Syntax:
{success} ← {new} CheckPath pathReturns a 1 if the path
to be checked is fine, otherwise 0.
- If
path
exists but is not a directory a 0 is returned. - If
path
does not exist a 0 is returned. - If
path
does not exist but the left argument is “CREATE!” it will be created, including any sub directories.
The left argument is case insensitive.
CopyTo
Syntax:
{(rc more)} ← source CopyTo targetCopies source
to target
.
The left argument must be one of:
- A filename (simple string).
- A vector of text strings, each representing a filename.
In case it is a single filename then the right argument must be either a directory (in which case the filename itself persists) or a filename.
In case the left argument is a vector of filenames the right argument must be either a single directory (all files are copied into that directory, and the filenames as such persist) or a vector of the same length as the left argument.
Note that wildcard characters are not supported.
CopyTo
overwrites the target file if there is any.
Examples:
'C:\readme.txt' FilesAndDirs2.CopyTo 'D:\buffer\'
'C:\readme.txt' FilesAndDirs2.CopyTo 'D:\buffer\newname.txt'
'C:\file1' 'C:\file2' FilesAndDirs2.CopyTo 'D:\buffer\'
'C:\file1' 'C:\file2' FilesAndDirs2.CopyTo 'D:\buffer\A' D:\buffer\B
The method always returns a (shy) two-item vector as result:
rc
is either 0 for “okay” or an error code.more
is an empty text vector in caserc
is 0. It might hold additional information in caserc
is not 0.
Note that in case source
is a nested vector of text vectors than both rc
and more
are nested as well, and the length will match the length of source
.
CopyTree
Syntax:
(success more list) ← source CopyTree targetOverview
source
must be an existing directory. target
must be either a existing directory or a name valid as a directory.
All files and folders in source
are copied over to target
.
Result
success
is Boolean with 1 indicating success. A 0 means failure, but the failure may not be total: in case, say, 100 files are to be copied and some of them failed because of a, say, ACCESS DENIED error thenrc
will be 0 butlist
gives you the full story.more
is empty if everything is okay. It may contain additional information if something goes wrong. An example is then thetarget
directory cannot be created.list
is a matrix with three columns:- [;0] is a list of names of all files and folders that were copied.
- [;1] is the return code: either 0 for success or an error number.
- [;2] is either an empty vector (in case of success) or additional information as a text vector.
Notes
CopyTree
does not rollback in case something goes wrong; instead it keeps trying.target
might already contain stuff; in case of name conflicts any already existing files will be overwritten.
CreateFile
Syntax:
tno ← {tno} CreateFile filenameSame as ⎕NCREATE
but filename
is normalized: every \
is exchanged by /
.
Returns the tie number.
DeleteFile
Syntax:
{success} ← DeleteFile filenamesAttempts to delete a file. Returns 1 in case of succes and 0 otherwise for each file in filenames
.
This function does not care whether the file exists or not, although naturally sucess
will be 0 for any non-existing files.
filenames
can be one of:
- Text string representing a single filename.
- Vector of text vectors, each representing a single file.
filenames
are normalized, meaning that any \
is replaced by /
.
In case filenames
is empty a 0 is returned.
Dir
Syntax:
r ← {parms_} Dir pathList contents of path
.
path
may be one of:
- A file:
Dir
returns attributes for just that file - A directory without a trailing slash:
Dir
returns attributes for just that directory - A directory with a trailing slash:
Dir
returns attributes for all files and directories found in that directory. - An empty vector: this defaults to
PWD,'/'
Note that *
and ?
are treated as wildcard characters. That means that FilesAndDirs
cannot deal with files that contain a *
or a ?
as part of any name, be it directory or filename; under Linux and Mac OS these are legal characters for filenames.
The result is a vector of the same length as type
which defaults to 0: just file- and directory names. You may specify additional attributes via the type
parameter either as key/value pairs or via a namespace populated with variables. If you do then the number of attributes specified defines the length of the result. Examples:
('recursive' 1) FilesAndDirs.Dir ''
parms←⎕ns''
parms.recursive←1
parms.type←3 4 5 1 0
parms FilesAndDirs.Dir ''
If path
is empty then the current directory is subject of Dir
.
Note that the names of parameters are case sensitive.
Parameter | Default | Meaning |
---|---|---|
follow | 0 | Shall symbolic links be followed |
recursive | 0 | Shall Dir scan path recursively |
type | 0 | Use this to select the information to be returned by Dir . 0 means names. For more information seehelp on ⎕NINFO . |
EnforceBackSlash
Syntax:
path ← EnforceBackSlash pathUse this if you must make sure that path
contains \
(Windows ony).
That problem might occur when you must pass a path to, say, a third-party software (7Zip is just an example) that refuses to accept /
characters under Windows.
Under non-Windows system this function does not take action ayt all.
Exists
Syntax:
bool ← Exists ySame as ⎕NEXISTS
but y
is normalized: any \
becomes /
. Note that is y
is a symbolic link that exists then a 1 will be returned, no matter whether the target the link is pointing to actually does exist or not.
GetNewLineCharsFor
Syntax:
newline ← GetNewLineCharsFor osReturns the proper newline
character(s) for os
or, if os
is empty, for the current OS.
GetTempFilename
Syntax:
filename ← {PrefixString} GetTempFilename pathReturns the name of an unused temporary filename. If path
is empty the default temp path is taken; that's what GetTempPath
would return. This means you can overwrite this by specifying a path.
PrefixString
, if defined, is a leading string of the filename going to be generated. This is not the same as
'pref',GetTempFileName ''
because specified as left argument it is taken into account when the uniqueness of the created filename is tested.
This function does not use the Windows built-in function since it has proven to be unreliable under W7 (at least).
GetTempPath
Syntax:
path ← GetTempPathReturns the path to the temp directory on the current system.
IsDir
Syntax:
r ← IsDir pathReturns 1 if path
is a directory and 0 otherwise, even if path
does exist as a file.
IsFile
Syntax:
r ← IsFile yReturns 1 if filename
is a regular file and a 0 otherwise, even if y
does exist as a directory.
y
must be either a text vector or a (negative!) tie number of a native file. If it is a number but not a tie number then an error is signalled.
IsSymbolicLink
Syntax:
r ← IsSymbolicLink yReturns a 1 if y
is a symbolic link and a 0 otherwise, even if y
does exist. y
must be a text vector.
ListDirs
Syntax:
r ← {recursive} ListDirs pathLists all directories (but nothing else) in path
.
path
must of course be a directory. Specify (not case sensitive) string “recursive” as left argument to make the function work recursively.
path
might contain wildcard characters (*
and ?
) but only in the last part of the path and only if “recursive” is not specified as left argument.
Returns a vector of text vectors in case anything was found and ''
otherwise.
ListFiles
Syntax:
r ← {recursive} ListFiles pathLists all files (but nothing else) in path
.
path
must of course be a directory. Specify (not case sensitive) string “recursive” as left argument to make the function work recursively.
path
might contain wildcard characters (*
and ?
) but only in the last part of the path and only if “recursive” is not specified as left argument.
Returns a vector of text vectors in case anything was found and ''
otherwise.
MkDir
Syntax:
{success} ← MkDir pathMake directory. If the directory already exists no action is taken and a 1 returned.
Any part of path
which does not already exist will be created in preparation of creating path
itself.
In comparison with ⎕MKDIR
there are two differences:
- This method normalizes
path
, meaning that any\
is changed into/
. - Errors 19 & 22 are trapped.
success
is 1 in case the directory was created successfully or already existed, otherwise 0.
MoveTo
Syntax:
{(rc more)} ← source MoveTo targetMoves source
to target
.
The function returns a return code and a textual message which is empty in case of success.
The left argument must be a either a text vector representing a filename or a vector of text vectors representing a vector of filenames.
The right argument might be a filename or a folder in case the left argument is a single filename. If the left argument is a vector of filenames then the right argument must be either a single directory name or a vector of te same length than the left argument with filenames and/or directory names.
If the right argument specifies a folder the filename part of source
is used for the new file.
Notes:
- ildcard characters are not supported.
- If you try to move a non-existing file you get a
¯1
as return code and an appropriate message onmore
. - If there is a name clash in
target
the already existing file will be overwritten.
The function returns a two-item vector. The first item is one of:
- ¯1 for internal errors (invalid argument(s) etc).
- 0 for success.
- OS error codes otherwise
The second item is an empty vector in case of success but may be a text vector with additional information otherwise.
Both items will be vectors themselves in case source
is a nested vector.
This function will move file(s) by first copying them over and then attempt to delete the source file. Note however that when the delete operation fails the copied file will be deleted. This is consistent with the behaviour of the Windows MoveFileEx
function.
Examples:
'C:\readme.txt' FilesAndDirs.MoveTo 'D:\buffer\'
'C:\readme.txt' FilesAndDirs.MoveTo 'D:\buffer\newname.txt'
MoveTree
Syntax:
(success more list) ← source MoveTree targetOverview
source
must be an existing directory. target
must be either a existing directory or a valid directory name.
All files and folders in source
are copied over to target
.
Result
success
is Boolean with 1 indicating success. A 0 means failure, but the failure may not be total: in case, say, 100 files are to be copied and just some of them failed because of a, say, an ACCESS DENIED error then rc
will be 0 but list
gives you the full story.
more
is empty if everything is okay. It may contain additional information if something goes wrong. An example is when the target
directory cannot be created.
list
is a matrix with four columns:
- [;0] is a list of names of all files and folders that were copied.
- [;1] is the copy-related return code: 0 for success or an error number.
- [;2] is the delete-related return code: 0 for success or an error number.
- [;3] is either an empty vector (in case of success) or additional information as a text vector.
Misc
Note that MoveTree
does not rollback in case something goes wrong; instead it keeps trying. That means that a copy-operation might be successful but the associated delete-operation fails.
Note that target
might already contain stuff; in case of name conflicts any already existing files will be overwritten.
NormalizePath
Syntax:
r ← {expandFlag} NormalizePath pathAll \
are converted to /
, no matter what operating system this code is running under.
This is in line with what Dyalog's ⎕N
functions are doing.
However, sometimes you need to pass a path with '' chars under Windows because otherwise a .NET call or a third-party software (7Zip is an example) refuse to work with /
chars. In that case you may use EnforceBackSlash
; see there.
Note that by default a relative path remains relative. You can change this by specifying “expand” as the (optional) left argument. In that case path
is expanded to an absolute path.
Notes:
- The left argument is not case sensitive.
- Any pair of
//
or\\
is reduced to a single/
or\
.
PolishCurrentDir
Syntax:
{r} ← PolishCurrentDirIf ⎕WSID
is relative (no /
or \
char in the path) the function does nothing.
Otherwise the current directory is changed so that it becomes the path part of ⎕WSID
.
Returns ''
or the old directory in case of a change.
PWD
Syntax:
r ← PWDPrint Work Directory; same as Cd''
.
RmDir
Syntax:
{(rc en more)} ← {mustBeEmpty} RmDir pathRemoves path
.
The method attempts to remove path
and, by default, all its contents.
If for some reason you want to make sure that path
is only removed when empty you can specify a 1 as left argument. In that case the method will not do anything if path
is not empty.
Note that this method may fail for reasons as trivial as somebody looking into path
at the moment of execution. However, the method may still be partly sucessful because it might have deleted files in path
before it actually fails to remove path
itself.
The result is a three-element vector:
rc
: return code that indicates success (0) or failure (1).en
: event number (⎕EN
) in case of an error.more
: empty text vector in caserc
is 0.
Note that wildcard characters (*
and ?
) are not allowed as part of path
. If such characters are specified anyway then an error is signalled.
Version
Syntax:
r ← Version- 1.1.1
- Documentation fixed (ADOC).
- 1.1.0
ListDirs
andListFiles
allow wildcard characters now.DeleteFiles
crashed on empty vectors.- Methods
IsFile
,IsDir
andIsSymbolicLink
except nested arguments now. - 1.0.0 - First version