6. Working with Files and Folders

## 6. Working with Files and Folders

The installation resources (files and directories) are grouped into `<folder>` elements.

    <project>
        ...
        <componentList>
           <component>
              <name>myComponent</name>
              ...
              <folderList>
                  <folder>
                     <name>documents</name>
                     <destination>${installdir}/docs</destination>
                     <platforms>linux windows</platforms>
                     <distributionFileList>
                         <distributionDirectory origin="/home/johndoe/docs"/>
                         <distributionFile origin="/home/johndoe/README"/>
                     </distributionFileList>
                     <shortcutList>
                         ...
                         <shortcut/>
                         ...
                     </shortcutList>
                     <actionList>
                         <addTextToFile file="${installdir}/docs/README" text="some text"/>
                     </actionList>
                  </folder>
              </folderList>
           </component>
        </componentList>
    </project>

The most important tags in a folder element are:

- `<distributionFileList>`: Contains the list of packed files. A directory (and its contents) is defined as a `<distributionDirectory>` while a file is represented through a `<distributionFile>`. All of the defined elements will be packed and unpacked at runtime. Both the `<distributionDirectory>` and `<distributionFile>` elements support the below tags:

  - `<origin>`: Path to the file or directory to pack in the build machine. If the path is relative, it will be absolutized when building using the project file parent directory as a reference.
  - `<allowWildcards>`: Configures whether or not the path configured in the `<origin>` tag must be considered a pattern (thus being resolved using global matching) or a literal location.
  - `<excludeFiles>`: When enabling `<allowWildcards>`, the list of files matching this pattern will be ignored. If `<allowWildcards>` is set to false, this pattern is ignored. See the Filters section for more information.
  - `<includeFiles>`: When enabling `<allowWildcards>`, only the list of files matching this pattern will be considered. If `<allowWildcards>` is set to false, this pattern is ignored. See the Filters section for more information.

    <folder>
       ...
       <distributionFileList>
           <distributionFile>
              <origin>${build_project_directory}/license.txt</origin>
           </distributionFile>
           <distributionDirectory allowWildcards="1">
              <origin>${build_project_directory}/readmeFiles/*.txt</origin>
              <includeFiles>*/README-*.txt</includeFiles>
              <excludeFiles>*/README-template.txt</excludeFiles>
           </distributionDirectory>
       </distributionFileList>
    </folder>

- `<platforms>`: This tag defines a space-separated list of platforms for which the files will be packed. This is evaluated at build time and matched against the specified build target. It allows a single project to define a multiplatform installer. The special platform identifier `all` can be used and represents all platforms. The full list of supported values in the tag is summarized in the table below:

Supported Platforms
Platform Identifier | Platform Description
all | All Platforms
linux | Linux
linux-x64 | Linux x86 64 bits
linux-ia64 | Linux IA64
windows | Windows
osx | Mac OS X
solaris-sparc | Solaris Sparc
solaris-intel | Solaris Intel
linux-ppc | Linux PPC
linux-s390 | Linux s390
linux-s390x | Linux s390x
freebsd | FreeBSD 5
freebsd4 | FreeBSD 4
freebsd6 | FreeBSD 6
freebsd6-x64 | FreeBSD 6 64 bits
freebsd7 | FreeBSD 7/8
freebsd7-x64 | FreeBSD 7/8 64 bits
openbsd3 | OpenBSD x86
hpux | HP-UX
aix | AIX, OS/400
irix-n32 | IRIX

- `<destination>`: The destination directory in which all the bundled files in the folder will be unpacked.
- `<shortcutList>`: Along with the files, a folder can define a list of shortcuts to create. You can find a detailed reference in the shortcuts section.
- `<actionList>`: Actions executed right after the files of the folder are unpacked.

### 6.1. Conditionally Packing a Folder

Although the `<platforms>` tag provides a built-in mechanism to avoid packing folders for different platforms, there are scenarios in which you need a more complex condition than just the target platform. This can be achieved using the `<shouldPackRuleList>`:

      <folder>
        <name>documents</name>
        <destination>${installdir}/docs</destination>
        <platforms>linux</platforms>
        <distributionFileList>
           <distributionDirectory origin="/home/johndoe/docs"/>
           <distributionFile origin="/home/johndoe/README"/>
        </distributionFileList>
        <shouldPackRuleEvaluationLogic>and</shouldPackRuleEvaluationLogic>
        <shouldPackRuleList>
           <fileExists path="/home/johndoe/docs"/>
           <fileExists path="/home/johndoe/README"/>
        </shouldPackRuleList>
      </folder>

The above folder will only be packed if the target platform is `linux` and the files exist. The evaluation logic of the rules can be modified through the `<shouldPackRuleEvaluationLogic>` property.

This is also helpful when you are developing the installer and do not need all of the files that will be included in the final version (that can greatly increase the build time) to be packed. For example, you could create an environment variable (`DEMO_BUILD`) to indicate to the builder you do not need an official build:

      <folder>
        <name>optionalFiles</name>
        <destination>${installdir}</destination>
        <platforms>linux</platforms>
        <distributionFileList>
           <distributionDirectory origin="videos"/>
           <distributionDirectory origin="images"/>
           <distributionDirectory origin="documentation"/>
        </distributionFileList>
        <shouldPackRuleList>
           <!-- Check if the variable is defined -->
           <compareText text="${env(DEMO_BUILD)}" logic="equals" value=""/>
        </shouldPackRuleList>
      </folder>

You can find a more complex example in the "Custom Build Targets" section.

| Do not confuse `<shouldPackRuleList>` with `<ruleList>`
Rules inside a `<ruleList>` are evaluated at runtime while rules within a `<shouldPackRuleList>` are evaluated at build time.

### 6.2. Conditionally Unpacking a Folder

By default, folders will be unpacked if they were packed (as described in the previous section) and if the `<component>` in which they are bundled was selected. However, you can add additional logic to discern if it should be unpacked by attaching rules to its `<ruleList>`:

      <folder>
        <name>documents</name>
        <destination>${installdir}/docs</destination>
        <platforms>windows</platforms>
        <distributionFileList>
           <distributionDirectory origin="/home/johndoe/docs"/>
           <distributionFile origin="/home/johndoe/README"/>
        </distributionFileList>
        <ruleEvaluationLogic>and</ruleEvaluationLogic>
        <ruleList>
           <platformTest type="windows-xp"/>
        </ruleList>
      </folder>

The above folder will be packed for any Windows target but will only be unpacked if the platform in which the installer is executing is Windows XP.

### 6.3. Filters

#### Basic Filters

InstallBuilder implements a basic filtering mechanism for folders. This functionality will allow you to pack the contents of a folder instead of including the folder itself and to apply filters to include or exclude specific files. For example, if you have a folder named "documentation" and you want to pack a subset of its contents and unpack it to `${installdir}/myDocs`, you just need to use the snippet below:

    <folder>
       <description>Documentation Files</description>
       <destination>${installdir}/myDocs</destination>
       <name>documentation</name>
       <platforms>all</platforms>
       <distributionFileList>
           <distributionDirectory allowWildcards="1">
              <origin>/some/path/to/documentation/*</origin>
              <includeFiles>*/project-1-*.txt</includeFiles>
              <excludeFiles>*/project-1-secret.txt</excludeFiles>
           </distributionDirectory>
       </distributionFileList>
    </folder>

In the above example, all of the .txt files related to "project-1" will be packaged, with the exception of "project-1-secret.txt"

The following are the filtering-related tags that you can use:

- `<allowWildcards>` : This tag determines the behavior of the filtering mechanism. If it is set to "0" (the default), there will not be any global pattern interpretation and patterns will be taken as literal strings. For example, if you define `<origin>/some/path/to/documentation/*</origin>`, the installer will look for a folder named `"*"` inside the `/some/path/to/documentation/` directory. In addition, the includeFiles and excludeFiles tags will be ignored.

However, if allowWildcards is set to `"1"`, the `<origin>` will be expanded and the installer will generate a list of matching files.

- `<includeFiles>` : This tag allows you to select files over the matches produced by the `<origin>` tag when wildcards are enabled. The default value of the `<includeFiles>` tag is `"*"` so all the files matched by the `<origin>` tag will be packed.
- `<excludeFiles>` : Once the list of files has been filtered with the `<includeFiles>` pattern, the `<excludeFiles>` filter will be applied over the result. The default value of this tag is empty so no filter is applied. This tag is ignored if wildcards are disabled. Only files directly returned by the evaluation of the `<origin>` pattern can be excluded, the builder won’t try to recursively exclude files at deeper hierarchy levels in the packed directories.

The pattern interpretation in the `<origin>`, `<includeFiles>` and `<excludeFiles>` does not follow the same rules. The `<origin>` pattern is expanded over the existing files, like a `"dir c:\Program Files\*txt"` on Windows or `"ls ~/*txt"` on Unix. Forward and backwards slashes are normalized according to the platform. However, the patterns in the `<includeFiles>` and `<excludeFiles>` tags follow a stricter format:

- Forward slashes are used as path separators, which let us escape special characters using backslashes. For example, to match .txt files, you must use `*/*.txt` files in both Windows and Unix systems.
- The pattern is applied over the full path of the files and a string comparison is performed: `<includeFiles>my.txt<includeFiles>` will not work because it will compare `"/some/path/to/my.txt"` with `"my.txt"`. `*/my.txt` has to be used instead.
- Multiple patterns can be included and must be separated by `;` or `\n` characters:

       <distributionDirectory allowWildcards="1">
           <origin>/some/path/*</origin>
           <includeFiles>*/*.txt;*/*.jpg;*/*.bmp</includeFiles>
           <excludeFiles>*/*secret*.txt;*/myImage.bmp</excludeFiles>
        </distributionDirectory>

The special characters used in all of the patterns are listed below:

- `?` : Matches any single character.
- `*` : Matches any sequence of zero or more characters.
- `[chars]` : Matches any single character in `chars`. If `chars` contains a sequence of the form `a-b` then any character between `a` and `b` (inclusive) will match.
- `{a,b,...}` : Matches any of the strings a, b, etc.

| Basic filters do not operate recursively
The basic filters mechanism is not intended to recursively skip packing files in the directory provided in the `<origin>` tag. Just the results returned by the evaluation of the `<origin>` pattern can be filtered. For example, if you are packing a directory `images` and want to exclude the file `demo.png`, the below won’t work:
    <folder>
       ...
       <destination>${installdir}</destination>
       ...
       <distributionFileList>
           <distributionDirectory allowWildcards="1">
              <origin>images</origin>
              <excludeFiles>*/demo.png</excludeFiles>
           </distributionDirectory>
       </distributionFileList>
    </folder>
The reason is that the `<origin>` pattern will only return `images` as matching file, which does not match the exclusion pattern `*/demo.png`. If `demo.png` is packed directly under `images` you could use:
    <folder>
       ...
       <destination>${installdir}/images</destination>
       ...
       <distributionFileList>
           <distributionDirectory allowWildcards="1">
              <origin>images/*</origin>
              <excludeFiles>*/demo.png</excludeFiles>
           </distributionDirectory>
       </distributionFileList>
    </folder>
In this case, evaluating `<origin>` will return all the contained images (`sample-01.png`, `left-image.jpg`, `details.gif`, demo.png, …), and the exclusion pattern will be able to match `demo.png`. If you want to filter certain files at any level of the hierarchy in the packed directory, you should use the Advanced Filters instead, which operate recursively.

#### Advanced Filters

In addition to the basic filters, which allow providing a pattern to the `<origin>` tag while excluding some of the results returned, InstallBuilder also includes a more complex filtering mechanism that allows excluding files located at any level in the folder hierarchy of the `<distributionDirectory>`.

Note that you have to define filters that will decide if the file will be packed or not. Currently, just filters based on the file path are allowed: `<fileNameFilter>`. These are the basic tags in the `<fileNameFilter>`:

- `<pattern>`: Pattern to match against the path of the file
- `<patternType>`: Whether to use glob or regular expressions matching
- `<logic>`: Whether or not the pattern must match to pass the filter.

These filters are grouped into the `<onPackingFilterList>`. If the file in consideration matches the expressed conditions in this list, it will be packed, if not, it will be skipped.

For example, if you want to pack a folder `dist-files`:

    dist-files/
    |-- bin
    |   `-- productA
    |       `-- data
    |           |-- info.ini
    |           `-- info.ini~
    |-- docs
    |   `-- reference
    |       |-- README.tct~
    |       |-- reference.html
    |       |-- reference.html~
    |       |-- reference.pdf
    |       `-- reference.pdf~
    `-- libraries
        |-- lib1.so
        |-- .#lib2.so
        `-- lib2.so

To exclude all of the temporary files (files ending in `~`), you could use:

     <folder>
       <description>Program Files</description>
       <destination>${installdir}</destination>
       <name>programfiles</name>
       <platforms>all</platforms>
       <distributionFileList>
         <distributionDirectory>
           <origin>dist-files</origin>
           <onPackingFilterList>
              <fileNameFilter pattern="*~" logic="does_not_match" patternType="glob"/>
           </onPackingFilterList>
         </distributionDirectory>
       </distributionFileList>
     </folder>

After the installation, you will find the `dist-files` directory clean of temporary files:

    sample-1.0
    |-- dist-files
    |   |-- bin
    |   |   `-- productA
    |   |       `-- data
    |   |           `-- info.ini
    |   |-- docs
    |   |   `-- reference
    |   |       |-- reference.html
    |   |       `-- reference.pdf
    |   `-- libraries
    |       |-- lib1.so
    |       |-- .#lib2.so
    |       `-- lib2.so
    |-- uninstall
    `-- Uninstall Sample Project.desktop

If you also want to exclude files starting with `.#`, you just need to add another filter to the `<onPackingFilterList>`:

     <folder>
       <description>Program Files</description>
       <destination>${installdir}</destination>
       <name>programfiles</name>
       <platforms>all</platforms>
       <distributionFileList>
         <distributionDirectory>
           <origin>dist-files</origin>
           <filterEvaluationLogic>and</filterEvaluationLogic>
           <onPackingFilterList>
              <fileNameFilter pattern="*~" logic="does_not_match" patternType="glob"/>
              <fileNameFilter pattern="*/.#*" logic="does_not_match" patternType="glob"/>
           </onPackingFilterList>
         </distributionDirectory>
       </distributionFileList>
     </folder>

The default `<filterEvaluationLogic>` is `and` but you can also set it to `or`. A file will be packed if its full path in the build machine matches all the filters when using `and` logic or when matching any of them when using `or`.

For example, if you want to pack just `.png` and `.jpg` files, you could rewrite the code with `or` logic:

     <folder>
       <description>Program Files</description>
       <destination>${installdir}</destination>
       <name>programfiles</name>
       <platforms>all</platforms>
       <distributionFileList>
         <distributionDirectory>
           <origin>dist-files</origin>
           <filterEvaluationLogic>or</filterEvaluationLogic>
           <onPackingFilterList>
              <fileNameFilter pattern="*.png" logic="matches" patternType="glob"/>
              <fileNameFilter pattern="*.jpg" logic="matches" patternType="glob"/>
           </onPackingFilterList>
         </distributionDirectory>
       </distributionFileList>
     </folder>

The filters can also include more complex patterns if instead of using the `glob` `<patternType>` you set it to `regexp`. For example, you can exclude `.txt` files that start with a number and contain `temp` in their paths and `.png` files that start with three capital letters using a single filter:

     <folder>
       <description>Program Files</description>
       <destination>${installdir}</destination>
       <name>programfiles</name>
       <platforms>all</platforms>
       <distributionFileList>
         <distributionDirectory>
           <origin>dist-files</origin>
           <onPackingFilterList>
              <fileNameFilter pattern="/([A-Z]{3}[^/]*\.png|[0-9]+[^/]*temp[^/]*\.txt)$" logic="does_not_match" patternType="regexp"/>
           </onPackingFilterList>
         </distributionDirectory>
       </distributionFileList>
     </folder>

Both `regexp` and `glob` pattern types allow providing a semicolon-separated list of sub patterns. If any of the sub patterns in the list evaluates to true, the full pattern will also evaluate to true. For example, to pack all of the `.png` and `.jpg` files in a directory, you could use any of the below snippets:

     <folder>
       <destination>${installdir}</destination>
       <name>programfiles</name>
       <distributionFileList>
         <distributionDirectory>
           <origin>dist-files</origin>
           <onPackingFilterList>
              <fileNameFilter pattern="*.png;*.jpg" logic="matches" patternType="glob"/>
           </onPackingFilterList>
         </distributionDirectory>
       </distributionFileList>
     </folder>

     <folder>
       <description>Program Files</description>
       <destination>${installdir}</destination>
       <name>programfiles</name>
       <platforms>all</platforms>
       <distributionFileList>
         <distributionDirectory>
           <origin>dist-files</origin>
           <filterEvaluationLogic>or</filterEvaluationLogic>
           <onPackingFilterList>
              <fileNameFilter pattern="*.jpg" logic="matches" patternType="glob"/>
              <fileNameFilter pattern="*.png" logic="matches" patternType="glob"/>
           </onPackingFilterList>
         </distributionDirectory>
       </distributionFileList>
     </folder>

     <folder>
       <destination>${installdir}</destination>
       <name>programfiles</name>
       <distributionFileList>
         <distributionDirectory>
           <origin>dist-files</origin>
           <filterEvaluationLogic>and</filterEvaluationLogic>
           <onPackingFilterList>
              <fileNameFilter pattern=".*\.(png|jpg)$" logic="matches" patternType="regexp"/>
           </onPackingFilterList>
         </distributionDirectory>
       </distributionFileList>
     </folder>

Even more complex conditions can be expressed using a `<filterGroup>`. This special type of filter allows grouping a set of filters with a configurable `<filterEvaluationLogic>`. For example, you can exclude all of the `.txt` files except for those in the `readme` folder and exclude all of the `.png` and `.jpg` files that are not under the `images` folder:

     <folder>
       <description>Program Files</description>
       <destination>${installdir}</destination>
       <name>programfiles</name>
       <platforms>all</platforms>
       <distributionFileList>
         <distributionDirectory>
           <origin>dist-files</origin>
           <filterEvaluationLogic>and</filterEvaluationLogic>
           <onPackingFilterList>
              <!-- Include files that do not end in .txt or if they are located in the readme dir -->
              <filterGroup>
                 <filterEvaluationLogic>or</filterEvaluationLogic>
                 <onPackingFilterList>
                   <fileNameFilter pattern="*.txt" logic="does_not_match" patternType="glob"/>
                   <fileNameFilter pattern="*/readme/*" logic="matches" patternType="glob"/>
                 </onPackingFilterList>
              </filterGroup>
              <!-- Include files that do not end in .png or .jpg or if they are located in the images dir -->
              <filterGroup>
                 <filterEvaluationLogic>or</filterEvaluationLogic>
                 <onPackingFilterList>
                   <fileNameFilter pattern=".*\.png;.*\.jpg" logic="does_not_match" patternType="regexp"/>
                   <fileNameFilter pattern="*/images/*" logic="matches" patternType="glob"/>
                 </onPackingFilterList>
              </filterGroup>
           </onPackingFilterList>
         </distributionDirectory>
       </distributionFileList>
     </folder>

Filter groups can also be nested as needed.

Take into account that all of the files in the `<distributionDirectory>` will be matched against the filter, so using a lot of very complex files could slightly increase the build time (the performance at runtime will not be affected at all).

| The pattern is applied to the full path of the file
Because of the pattern is applied to the full path of the file to be packed, when trying to match files ending in an specific suffix, you should always prefix it with * (when using `glob` `<patternType>`) or `.*` (when using `regexp` `<patternType>`). For example, specifying:
    <fileNameFilter pattern="images/*.png" logic="matches" patternType="glob"/>
Wont work because it will be matched against the full path, for example: `/home/bitrock/demo/files/images/foo.png` To make it independent to the location, it should be rewritten to:
    <fileNameFilter pattern="*/images/*.png" logic="matches" patternType="glob"/>
Or
    <fileNameFilter pattern="${build_project_directory}/files/images/*.png" logic="matches" patternType="glob"/>

### 6.4. Unix Permissions

InstallBuilder preserves the permissions of bundled files. It also includes two convenient tags: `<defaultUnixGroup>` and `<defaultUnixOwner>`. If a value is specified for those tags, the owner and group of the unpacked files will be modified at runtime:

    <project>
       ...
       <defaultUnixGroup>wheel</defaultUnixGroup>
       <defaultUnixOwner>root</defaultUnixOwner>
       ...
    </project>

Please take into account that the specified group and owner must exist in the target machine. If not, you can always create them before the installation phase:

    <project>
       ...
       <defaultUnixGroup>coolUsers</defaultUnixGroup>
       <defaultUnixOwner>john</defaultUnixOwner>
       ...
       <readyToInstallActionList>
          <addUser username="john"/>
          <addGroup groupname="coolUsers"/>
       </readyToInstallActionList>
       ...
    </project>

Despite the permissions being preserved, in some situations they must be fixed. The most convenient way of fixing them is to use the `<actionList>` of the folder containing the files and set the appropriate rights:

    <folder>
       <description>Binary Files</description>
       <destination>${installdir}</destination>
       <name>executables</name>
       <platforms>all</platforms>
       <distributionFileList>
           <distributionDirectory>
              <origin>/some/path/executables</origin>
           </distributionDirectory>
       </distributionFileList>
       <actionList>
           <changePermissions permissions="0755" files="${installdir}/executables/*"/>
       </actionList>
    </folder>

A common scenario in which permissions must be fixed is when you are building a Linux installer on Windows. In that case, you could either manually fix the permissions as explained in the latest snippet or define the default permissions:

    <project>
       ...
       <defaultUnixFilePermissions>644</defaultUnixFilePermissions>
       <defaultUnixDirectoryPermissions>755</defaultUnixDirectoryPermissions>
       ...
    </project>

Please take into account that, contrary to the owner and group tags, the default Unix permissions are only applied when building on Windows. This way, if the installer is created on Unix, the configured values will be ignored.

| Files packed on Windows lose their executable permissions
Windows does not understand Unix permissions, so Unix installers created on Windows will be unpacked without executable permissions and must be manually fixed. It is recommended that you use Unix machines to build the installers as they do not present any limitation.

### 6.5. Symbolic Links

When a symbolic link is specified as a `<distributionFile>`, InstallBuilder does not follow the link to pack its target. Depending on the build type, it will either pack the link (deb, rpm) or it will be registered and recreated at runtime.

### 6.6. Unpacking Before Installation Time

It is common to have a separate tool or program that must be bundled with and run from the installer but before the file copying phase of the installation process has completed. A common example would be a license validation program. Typically, all files bundled within an installer are unpacked and then any tools are run. In the case of a license validation tool, that is less than ideal because the user may end up waiting for the files to be unpacked only to find that the license is not valid. The user would then have to wait for the installation to be rolled back.

InstallBuilder provides you with actions to deal with these situations. The most important are `<unpackFile>` and `<unpackDirectory>`:

    <unpackDirectory>
       <destination>${installdir}</destination>
       <component>tools</component>
       <folder>license</folder>
       <origin>management</origin>
    </unpackDirectory>

    <unpackFile>
       <destination>${system_temp_directory}</destination>
       <component>tools</component>
       <folder>license</folder>
       <origin>management/validator.exe</origin>
    </unpackFile>

The `<unpackDirectory>` action is intended to unpack a directory and its contents while the `<unpackFile>` action operates over files. Trying to unpack the wrong type in those actions will generate an error at runtime.

The configuration options for these actions specify the folder and component bundling the files, the path relative to the packed element, and the destination directory to unpack them.

The structure in Figure 33 (also represented in XML code) should help you understand how to reference internal files:

Figure 33. Internal Files Structure

    <project>
      ...
      <componentList>
         <component>
           <name>componentA</name>
           <description>Component A</description>
           <folderList>
             <folder>
               <name>folder1</name>
               <description>Folder 1</description>
               <distributionFileList>
                  <distributionDirectory>
                    <!-- someDirectory contains: readme.txt,
                    logo.jpg and directory1 -->
                    <origin>/path/to/someDirectory</origin>
                  </distributionDirectory>
                  <distributionFile>
                    <origin>/path/to/someFile</origin>
                  </distributionFile>
                  <distributionFile>
                    <origin>/path/to/someOtherFile</origin>
                  </distributionFile>
               </distributionFileList>
             </folder>
           </folderList>
         </component>
         <component>
           <name>componentB</name>
           <description>Component B</description>
           <folderList>
             <folder>
               <name>folder2</name>
               <description>Folder 2</description>
               <distributionFileList>
                  <distributionDirectory>
                    <!-- someDirectory contains: movie.avi and
                    installer.exe -->
                    <origin>/path/to/someOtherDirectory</origin>
                  </distributionDirectory>
               </distributionFileList>
             </folder>
           </folderList>
         </component>
      </componentList>
      ...
    </project>

To reference `logo.jpg`:

    <unpackFile>
      <component>componentA</component>
      <folder>folder1</folder>
      <origin>someDirectory/logo.jpg</origin>
      <destination>${installdir}</destination>
    </unpackFile>

You could also unpack `directory1`:

    <unpackDirectory>
      <component>componentA</component>
      <folder>folder1</folder>
      <origin>someDirectory/directory1</origin>
      <destination>${installdir}</destination>
    </unpackDirectory>

Please note the `<origin>` is always provided as the relative path to the file or directory to unpack, relative to the `<folder>` containing it. It does not matter where the file was originally located in the building machine, just the path inside the installer:

    <component name="componentA">
       <folderList>
         <folder>
           <name>folder1</name>
           <distributionFileList>
             <distributionDirectory>
                <origin>/some/long/path/in/the/building/machine/someDirectory</origin>
             </distributionDirectory>
           </distributionFileList>
         </folder>
       </folderList>
    </component>

The example below details a real scenario, in which the installer unpacks a license validator and checks the provided key in the `<validationActionList>` of the page:

    <project>
      ...
      <componentList>
        <component>
        <name>tools</name>
           <folderList>
              <folder>
                 <name>license</name>
                 <destination>${installdir}</destination>
                 <distributionFileList>
                    <!-- The management directory contains a lot of
                    tools, one of the our validator.exe -->
                    <distributionDirectory origin="/path/to/dir/to/management"/>
                 </distributionFileList>
              </folder>
           </folderList>
        </component>
      </componentList>
      <parameterList>
        <stringParameter>
           <name>licenseCheck</name>
           <description>Introduce your license key</description>
           <value></value>
           <validationActionList>
             <unpackFile>
                <component>tools</component>
                <folder>license</folder>
                <!-- Relative path from the packed folder 'management' -->
                <origin>management/validator.exe</origin>
                <destination>${system_temp_directory}</destination>
             </unpackFile>
             <runProgram>
               <program>${system_temp_directory}/validator.exe</program>
               <programArguments>${project.parameter(licenseCheck).value}</programArguments>
             </runProgram>
             <throwError text="Wrong license key, please enter a valid one">
               <ruleList>
                 <compareText text="${program_stdout}" logic="equals" value="1"/>
               </ruleList>
             </throwError>
           </validationActionList>
        </stringParameter>
      </parameterList>
        ...
    </project>

5. Components |  | 7. User Input