Author image Grant Street Group
and 1 contributors


YAML::LoadBundle - Load a directory of YAML files as a bundle


version v0.4.2


  use YAML::LoadBundle qw(:all);

  my $hash = load_yaml_bundle( "/path/to/yaml_bundle/dir/" );


Adds additonal features to YAML::XS to allow splitting a YAML file into multiple files in a common directory. This helps with readability when the file is large.

It also provides more advanced merging features than the standard YAML spec.


Nothing is exported by default, but all the functions listed below are available for export.

All will be exported with :all.

Exported Functions




Parses a YAML file (or string) with extra error-checking.

When passed a $filename, the %YAML_cache will cache a dclone'd copy of the result for later retrieval, unless the file has been modified since the last load. This can be prevented by passing anything else as a 2nd parameter, if you know that the file will never be reloaded.

When passed a string, the %YAML_cache will cache a copy of the result, using the SHA1 digest of the string as the hash key. Strings are only cached in memory, not on disk.

After loading the YAML into a Perl data structure, some postprocessing is done on specially-named keys in hash references. Each is merged into their containing hash reference, though at different times and with different strategies.

  • -import

    shallow merge (e.g. %x = (%y, %x))

  • -export

    shallow merge

  • -merge

    deep merge (see Hash::Merge::Simple)

  • <-flatten>

        some_key: { -flatten: [*SomeArrayRef, *SomeOtherArrayRef] }

    Instead of doing any kind of special hash merging, this special key takes an arrayref of arrayrefs, merges all their contents into one large arrayref, then replaces its entire surrounding hash with the arrayref.

    In other words, the example above would look like this in Perl:

        { some_key => [@$some_array_ref, @$some_other_array_ref] }
  • -flattenhash

        some_key: { -flattenhash: [*SomeHashRef, *SomeOtherHashRef] }

    Sometimes it is desirable to import more than one hash object, but cannot due to limitations of keynames like -import. If you really want this behavior, add this flag.

import and export are backwards-compatibility synonyms for -import and -export.

Like normal list assignment in Perl, the right-hand side takes precedence (pseudocode):

  %hash = deep_merge(%merge, shallow_merge(%import, %export, %hash));

Instead of a hash reference, any of these keys may contain an array reference of hash references, in which case those hash references are merged using whatever strategy normally applies (e.g. deep merge for -merge).


  load_yaml_bundle($path, \%options)

Similar to "load_yaml", but loads YAML from a bundle of configuration files. This may be a single file, a directory containing configuration files, or a whole directory tree of configuration files.

The given path names the base location for the bundle. This starts by loading a file with the given name followed by a configuration prefix (either .yml or .conf by default). It then checks to see if there is a directory with the same name as the path. It then repeats the loading process for all nested files and directories where the file and directory names become the keys into which the configuration is injected.

For example, given a directory layout like this:


A hash would be returned mapped something like this (pseudo-code):

        common => load_yaml("conf/base/common.conf"),
        user   => {
            accounts => load_yaml("conf/base/user/accounts.conf"),
            %{ load_yaml("conf/base/user.conf") }
        %{ load_yaml("conf/base.conf") }

However, the actual merge will be a deep merge.

The usual semantics related to import, export, and merging apply to these files as they do in "load_yaml".

Symlinks can be used to share the data between multiple keys. By default, symlinks will be followed, but will cause an error if any of them are outside the root path of the bundle. If a symlink is permitted, this will follow symlinks to files or directories as if they were the files or directories set locally, allowing the original key to be renamed in any way desired. It also means that symlinks to files must have a correct configuraiton file suffix.

This will ignore any file starting with a period.

There are some options to modify the default behaviors:

This may be set to any of the following strings:


This is the default. Symlinks are followed, but only within the root.


Do not follow symlinks.


Always follow symlinks. Use this with caution.

This may be set to any of the following strings:


This is the default. When symlinks are found, but not followed, croak.


When symlinks are found, but not followed, carp.


When symlinks are found, but not followed... take no action at all.


This routine only considers files that have the given suffxes. The default includes "conf" and "yml". The suffixes are given as an array reference of strings. (All directories will be followed, at least to the maximum depth.)


This defaults to 20 which is probably more than enough and mostly intended to prevent some sort of insane failure. If a directory is found at one further than the maximum depth, a warning will be issued.



    add_yaml_observer(sub {
        my $filename = shift;
        warn "Yaml file $filename was just loaded.";

Adds an observer sub that will be notified just prior to a yaml file being loaded. Note that each observer is called even if the yaml file is cached and does not need to be reloaded.


Called internally to notify each waiting observer that a new yaml file is being loaded.



Removes an observer sub that was previously added via add_yaml_observer.



Set this to a path that already exists of where to cache loaded files.

        = File::Spec->catdir( File::Spec->tmpdir, 'yaml-loadbundle' );


If false, caching is disabled.


Grant Street Group <>


This software is Copyright (c) 2016 - 2020 by Grant Street Group.

This is free software, licensed under:

  The Artistic License 2.0 (GPL Compatible)