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

Go to: top

Reference

Included

Shared Methods

Go to: top

Cd

Syntax:r ← Cd path

Reports 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).

Go to: top

CheckPath

Syntax:{success} ← {new} CheckPath path

Returns 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.

Go to: top

CopyTo

Syntax:{(rc more)} ← source CopyTo target

Copies 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:

  1. rc is either 0 for “okay” or an error code.
  2. more is an empty text vector in case rc is 0. It might hold additional information in case rc 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.

Go to: top

CopyTree

Syntax:(success more list) ← source CopyTree target

Overview

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

Notes

Go to: top

CreateFile

Syntax:tno ← {tno} CreateFile filename

Same as ⎕NCREATE but filename is normalized: every \ is exchanged by /.

Returns the tie number.

Go to: top

DeleteFile

Syntax:{success} ← DeleteFile filenames

Attempts 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.

Go to: top

Dir

Syntax:r ← {parms_} Dir path

List 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 see
help on ⎕NINFO.
Go to: top

EnforceBackSlash

Syntax:path ← EnforceBackSlash path

Use 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.

Go to: top

Exists

Syntax:bool ← Exists y

Same 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.

Go to: top

GetNewLineCharsFor

Syntax:newline ← GetNewLineCharsFor os

Returns the proper newline character(s) for os or, if os is empty, for the current OS.

Go to: top

GetTempFilename

Syntax:filename ← {PrefixString} GetTempFilename path

Returns 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).

Go to: top

GetTempPath

Syntax:path ← GetTempPath

Returns the path to the temp directory on the current system.

Go to: top

IsDir

Syntax:r ← IsDir path

Returns 1 if path is a directory and 0 otherwise, even if path does exist as a file.

Go to: top

IsFile

Syntax:r ← IsFile y

Returns 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.

Go to: top
Syntax:r ← IsSymbolicLink y

Returns a 1 if y is a symbolic link and a 0 otherwise, even if y does exist. y must be a text vector.

Go to: top

ListDirs

Syntax:r ← {recursive} ListDirs path

Lists 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.

Go to: top

ListFiles

Syntax:r ← {recursive} ListFiles path

Lists 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.

Go to: top

MkDir

Syntax:{success} ← MkDir path

Make 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.
Go to: top

MoveTo

Syntax:{(rc more)} ← source MoveTo target

Moves 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 on more.
  • 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' 
Go to: top

MoveTree

Syntax:(success more list) ← source MoveTree target

Overview

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:

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.

Go to: top

NormalizePath

Syntax:r ← {expandFlag} NormalizePath path

All \ 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 \.
Go to: top

PolishCurrentDir

Syntax:{r} ← PolishCurrentDir

If ⎕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.

Go to: top

PWD

Syntax:r ← PWD

Print Work Directory; same as Cd''.

Go to: top

RmDir

Syntax:{(rc en more)} ← {mustBeEmpty} RmDir path

Removes 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:

  1. rc: return code that indicates success (0) or failure (1).
  2. en: event number (⎕EN) in case of an error.
  3. more: empty text vector in case rc 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.

Go to: top

Version

Syntax:r ← Version
  • 1.1.1
    • Documentation fixed (ADOC).
  • 1.1.0
    • ListDirs and ListFiles allow wildcard characters now.
    • DeleteFiles crashed on empty vectors.
    • Methods IsFile, IsDir and IsSymbolicLink except nested arguments now.
  • 1.0.0 - First version