A while ago Colin Putney announced the Filesystem framework, a nice and extensible replacement for the ugly
FileDirectory class in Pharo. While all core classes are well commented, there is a quick start missing that explains how end users are supposed to adopt the framework. This blog post should fill that gap.
First we need to load the package:
The framework supports different kinds of filesystems that can be used interchangeably and that can transparently work with each other. The most obvious one is the filesystem on your hard disk. We are going to work with that one for now:
working := FSDiskFilesystem current working.
Put the above code into a workspace and evaluate it. It assigns a reference of the current working directory to the variable
working. References are the central object of the framework and provide the primary mechanism of working with files and directories. All code below works on
Now lets do some more interesting things. To list all children of your working directory evaluate the following expression:
To iterate over all children recursively evaluate:
To get a reference to a specific file or directory within your working directory use the slash operator:
cache := working / 'package-cache'.
Navigating back to the parent is easy:
You can check for various properties of the
cache directory by evaluating the following expressions:
cache exists. "--> true"
cache isFile. "--> false"
cache isDirectory. "--> true"
cache basename. "--> 'package-cache'"
To get additional information about the filesystem entry evaluate:
cache entry creation. "--> 2010-02-14T10:34:31+00:00"
cache entry modification. "--> 2010-02-14T10:34:31+00:00"
cache entry size. "--> 0 (directories have size 0)"
The framework also supports locations, late-bound references that point to a file or directory. When asking to perform a concrete operation, a location behaves the same way as a reference. Currently the following locations are supported:
If you save a location with your image and move the image to a different machine or operating system, a location will dynamically adapt and always point to the place you would expect.
To open a file-stream on a file ask the reference for a read- or write-stream:
stream := (working / 'foo.txt') writeStream.
stream nextPutAll: 'Hello World'.
stream := (working / 'foo.txt') readStream.
Please note that
#writeStream overrides any existing file and
#readStream throws an exception if the file does not exist. There are also short forms available:
working / 'foo.txt' writeStreamDo: [ :stream | stream nextPutAll: 'Hello World' ].
working / 'foo.txt' readStreamDo: [ :stream | stream contents ].
Have a look at the
streams protocol of
FSReference for other convenience methods.
You can also copy and rename files by evaluating:
(working / 'foo.txt') copyTo: (working / 'bar.txt').
To create a directory evaluate:
backup := working / 'cache-backup'.
And then to copy the contents of the complete package-cache to that directory simply evaluate:
cache copyAllTo: backup.
Note, that the target directory would be automatically created, if it was not there before.
To delete a single file evaluate:
(working / 'bar.txt') delete.
To delete a complete directory tree use the following expression. Be careful with that one though.
That’s the basic API of the Filesystem library. If there is interest we can have a look at other features and other filesystem types in a next iteration.