Skip to main content
Engineering LibreTexts

2.5: The Main Entry Point - FileReference

  • Page ID
    43796
  • \( \newcommand{\vecs}[1]{\overset { \scriptstyle \rightharpoonup} {\mathbf{#1}} } \) \( \newcommand{\vecd}[1]{\overset{-\!-\!\rightharpoonup}{\vphantom{a}\smash {#1}}} \)\(\newcommand{\id}{\mathrm{id}}\) \( \newcommand{\Span}{\mathrm{span}}\) \( \newcommand{\kernel}{\mathrm{null}\,}\) \( \newcommand{\range}{\mathrm{range}\,}\) \( \newcommand{\RealPart}{\mathrm{Re}}\) \( \newcommand{\ImaginaryPart}{\mathrm{Im}}\) \( \newcommand{\Argument}{\mathrm{Arg}}\) \( \newcommand{\norm}[1]{\| #1 \|}\) \( \newcommand{\inner}[2]{\langle #1, #2 \rangle}\) \( \newcommand{\Span}{\mathrm{span}}\) \(\newcommand{\id}{\mathrm{id}}\) \( \newcommand{\Span}{\mathrm{span}}\) \( \newcommand{\kernel}{\mathrm{null}\,}\) \( \newcommand{\range}{\mathrm{range}\,}\) \( \newcommand{\RealPart}{\mathrm{Re}}\) \( \newcommand{\ImaginaryPart}{\mathrm{Im}}\) \( \newcommand{\Argument}{\mathrm{Arg}}\) \( \newcommand{\norm}[1]{\| #1 \|}\) \( \newcommand{\inner}[2]{\langle #1, #2 \rangle}\) \( \newcommand{\Span}{\mathrm{span}}\)\(\newcommand{\AA}{\unicode[.8,0]{x212B}}\)

    While FileSystem is based on multiple concepts and classes such as FileSystem, Path and FileReference. FileReference is the most important for an end-user. FileReference offers a set of operations to manipulate files. So far, we have seen some basic operations. This section covers the more elaborated operations.

    At the design level, a file reference (FileReference) combines two low-level entities: a path (Path) and a filesystem (FileSystem) into a single object which provides a simple protocol to manipulate and handle files. A FileReference implements many operations of FileSystem (both are largely polymorphic), but without the need to track paths and filesystem separately.

    FileReference information access

    Once given a file reference you can access usual information using messages basename, base, extensions...

    | pf |
    pf := (FileSystem disk workingDirectory / 'package-cache' ) children second.
        → /Users/ducasse/Pharo/PharoHarvestingFixes/20/package-cache/AsmJit-
            IgorStasenko.66.mcz
    pf fullName
        → '/Users/ducasse/Pharo/PharoHarvestingFixes/20/package-cache/AsmJit-
        IgorStasenko.66.mcz'
    pf basename
        → 'AsmJit-IgorStasenko.66.mcz'
    pf basenameWithoutExtension
        → 'AsmJit-IgorStasenko.66'
    pf base
        → 'AsmJit-IgorStasenko'
    pf extension
        → 'mcz'
    pf extensions
        → an OrderedCollection('66' 'mcz')
    

    Indicators. FileSystem introduces the notion of file reference indicators. An indicator is a visual clue conveying the type of the reference. For now three kind of indicators are implemented, '?' for a non existing reference, '/' for a directory, and the empty string for a file. FileReference defines the message basenameWithIndicator that takes advantage of indicators. The following expressions show its use.

    pf basenameWithIndicator
        → 'AsmJit-IgorStasenko.66.mcz'
    pf parent basename
        → 'package-cache'
    pf parent basenameWithIndicator
        → 'package-cache/'
    

    Path. When there is a need to access a portion of a path, the message pathSegments returns the full name cut into path elements, as strings. Remember that from a design point of view, strings are considered as “dead” objects, so it is often better to deal with the real objects for example using the path message.

    pf pathSegments
        → #('Users' 'ducasse' 'Pharo' 'PharoHarvestingFixes' '20' 'package-cache' '
            AsmJit-IgorStasenko.66.mcz')
    pf path
        → Path / 'Users' / 'ducasse' / 'Pharo' / 'PharoHarvestingFixes' / '20' / 'package-
            cache' / 'AsmJit-IgorStasenko.66.mcz'
    

    Sizes. FileReference provides also some way to access the size of the file.

    pf humanReadableSize
        → '182.78 kB'
    pf size
        → 182778
    

    File Information. You can get limited information about the file entry itself using creationTime and permissions. To get the full information you should access the entry itself using the message entry.

    | pf |
    pf := (FileSystem disk workingDirectory / 'package-cache' ) children second.
    pf creationTime.
        → 2012-06-10T10:43:19+02:00
    pf modificationTime.
        → 2012-06-10T10:43:19+02:00
    pf permissions
        → rw-r--r--
    

    Entries are objects that represent all the metadata of a single file.

    | pf |
    pf := (FileSystem disk workingDirectory / 'package-cache' ) children second.
    pf entry
    
    pf parent entries
        "returns all the entries of the children of the receiver"
    

    Operating on files

    There are several operations on files.

    Deleting. delete, deleteAll, deleteAllChildren, all delete the receiver and raise an error if it does not exist. delete deletes the file, deleteAll deletes the directory and its contents, deleteAllChildren (which only deletes children of a directory). In addition, deleteIfAbsent: executes a block when the file does not exist.

    Finally ensureDelete deletes the file but does not raise error if the file does not exist. Similarly ensureDeleteAllChildren, ensureDeleteAll do not raise exception when the receiver does not exist.

    (FileSystem disk workingDirectory / 'paf') delete.
        → error
    (FileSystem disk workingDirectory / 'fooFolder') deleteAll.
        → error
    (FileSystem disk workingDirectory / 'fooFolder') ensureCreateDirectory.
    (FileSystem disk workingDirectory / 'fooFolder') deleteAll.
    
    (FileSystem disk workingDirectory / 'paf') deleteIfAbsent: [Warning signal: 'File did not
        exist'].
    (FileSystem disk workingDirectory / 'fooFolder2') deleteAllChildren.
        → error
    
    (FileSystem disk workingDirectory / 'fooFolder2') ensureCreateDirectory.
    (FileSystem disk workingDirectory / 'fooFolder2') deleteAllChildren.
    

    Creating Directory. createDirectory creates a new directory and raises an error if it already exists. ensureCreateDirectory verifies that the directory does not exist and only creates it if necessary. ensureCreateFile creates if necessary a file.

    (FileSystem disk workingDirectory / 'paf' ) createDirectory.
    [(FileSystem disk workingDirectory / 'paf' ) createDirectory] on: DirectoryExists do: [:ex|
        true].
        → true
    (FileSystem disk workingDirectory / 'paf' ) delete.
    (FileSystem disk workingDirectory / 'paf' ) ensureCreateDirectory.
    (FileSystem disk workingDirectory / 'paf' ) ensureCreateDirectory.
    (FileSystem disk workingDirectory / 'paf' ) isDirectory.
        → true
    

    Moving/Copying files around. We can move files around using the message moveTo: which expects a file reference.

    (FileSystem disk workingDirectory / 'targetFolder') exist
        → false
    (FileSystem disk workingDirectory / 'paf') exist
        → false
    (FileSystem disk workingDirectory / 'paf' ) moveTo: (FileSystem disk workingDirectory / '
            targetFolder')
        → Error
    
    (FileSystem disk workingDirectory / 'paf' ) ensureCreateFile.
    (FileSystem disk workingDirectory / 'targetFolder') ensureCreateDirectory.
    (FileSystem disk workingDirectory / 'paf' ) moveTo: (FileSystem disk workingDirectory / '
        targetFolder' / 'paf').
    (FileSystem disk workingDirectory / 'paf' ) exists.
        → false
    (FileSystem disk workingDirectory / 'targetFolder' / 'paf') exists.
        → true
    

    Besides moving files, we can copy them. We can also use copyAllTo: to copy files. Here, we copy the files contained in the source folder to the target one.

    The message copyAllTo: performs a deep copy of the receiver, to a location specified by the argument. If the receiver is a file, the file is copied. If the receiver is a directory, the directory and its contents will be copied recursively.

    The argument must be a reference that does not exist; it will be created by the copy.

    (FileSystem disk workingDirectory / 'sourceFolder') createDirectory.
    (FileSystem disk workingDirectory / 'sourceFolder' / 'pif') ensureCreateFile.
    (FileSystem disk workingDirectory / 'sourceFolder' / 'paf') ensureCreateFile.
    (FileSystem disk workingDirectory / 'targetFolder') createDirectory.
    (FileSystem disk workingDirectory / 'sourceFolder') copyAllTo: (FileSystem disk
        workingDirectory / 'targetFolder').
    (FileSystem disk workingDirectory / 'targetFolder' / 'pif') exists.
        → true
    (FileSystem disk workingDirectory / 'targetFolder' / 'paf') exists.
        → true
    

    The message copyAllTo: can be used to copy a single file too:

    (FileSystem disk workingDirectory / 'sourceFolder') ensureCreateDirectory.
    (FileSystem disk workingDirectory / 'sourceFolder' / 'pif') ensureCreateFile.
    (FileSystem disk workingDirectory / 'sourceFolder' / 'paf') ensureCreateFile.
    (FileSystem disk workingDirectory / 'targetFolder') ensureCreateDirectory.
    (FileSystem disk workingDirectory / 'sourceFolder' / 'paf') copyAllTo: (FileSystem disk
        workingDirectory / 'targetFolder' / 'paf').
    (FileSystem disk workingDirectory / 'targetFolder' / 'paf') exists.
        → true.
    (FileSystem disk workingDirectory / 'targetFolder' / 'pif' ) exists.
        → false
    

    Locator

    Locators are late-bound references. They are left deliberately fuzzy, and are only resolved to a concrete reference when some file operation is performed. Instead of a filesystem and path, locators are made up of an origin and a path. An origin is an abstract filesystem location, such as the user’s home directory, the image file, or the VM executable. When it receives a message like isFile, a locator will first resolve its origin, then resolve its path against the origin.

    Locators make it possible to specify things like "an item named ’package-cache’ in the same directory as the image file" and have that specification remain valid even if the image is saved and moved to another directory, possibly on a different computer.

    locator := FileLocator imageDirectory / 'package-cache'.
    locator printString.        → ' {imageDirectory}/package-cache'
    locator resolve.            → /Users/ducasse/Pharo/PharoHarvestingFixes/20/
        package-cache
    locator isFile.             → false
    locator isDirectory.        → true
    

    The following origins are currently supported:

    • imageDirectory - the directory in which the image resides
    • image - the image file
    • changes - the changes file
    • vmBinary - the executable for the running virtual machine
    • vmDirectory - the directory containing the VM application (may not be the parent of vmBinary)
    • home - the user’s home directory
    • desktop - the directory that holds the contents of the user’s desktop
    • documents - the directory where the user’s documents are stored (e.g. ’/Users/colin/Documents’)

    Applications may also define their own origins, but the system will not be able to resolve them automatically. Instead, the user will be asked to manually choose a directory. This choice is then cached so that future resolution requests will not require user interaction.

    absolutePath vs. path. The message absolutePath returns the absolute path of the receiver. When the file reference is not virtual the messages path and absolutePath provide similar results. When the file is a late bound reference (instance of FileLocator), absolutePath resolves the file and returns the absolute path, while path returns an unresolved file reference as shown below.

    (FileLocator image parent / 'package-cache') path
        → {image}/../package-cache
    
    (FileLocator image parent / 'package-cache') absolutePath
        → Path / 'Data' / 'Downloads' / 'Pharo-2.0' / 'package-cache'
    
    (FileLocator image parent / 'package-cache') absolutePath
        → Path / 'Data' / 'Downloads' / 'Pharo-2.0' / 'package-cache' 
    

    References and Locators also provide simple methods for dealing with whole directory trees.


    This page titled 2.5: The Main Entry Point - FileReference is shared under a CC BY-SA 3.0 license and was authored, remixed, and/or curated by Alexandre Bergel, Damien Cassou, Stéphane Ducasse, Jannik Laval (Square Bracket Associates) via source content that was edited to the style and standards of the LibreTexts platform; a detailed edit history is available upon request.