diff --git a/libraries.api.php b/libraries.api.php
index ac09743..17c086a 100644
--- a/libraries.api.php
+++ b/libraries.api.php
@@ -164,8 +164,16 @@
  *       Note that in this group the 'versions' property is no longer available.
  *     - pre-load: Callbacks registered in this group are applied directly
  *       before this library is loaded. At this point the library contains
- *       variant-specific information, if specified. Note that in this group the
- *       'variants' property is no longer available.
+ *       variant-specific information, if specified, and following additional
+ *       information is available:
+ *       - $library['variant']: The variant of the library that is about to be
+ *         loaded.
+ *       The following pre-load callbacks are available for all libraries:
+ *       - libaries_replace_filenames: Use this callback if your library files
+ *         have version- or variant-dependant filenames. The callback replaces
+ *         all occurences of '!version' in filenames with the detected library
+ *         version and all occurences of '!variant' with the variant.
+ *       Note that in this group the 'variants' property is no longer available.
  *     - post-load: Callbacks registered in this group are applied directly
  *       after this library is loaded. At this point, the library contains a
  *       'loaded' key, which contains the number of files that were loaded.
diff --git a/libraries.info b/libraries.info
index 208a14e..b70306e 100644
--- a/libraries.info
+++ b/libraries.info
@@ -2,3 +2,5 @@ name = Libraries
 description = Allows version dependent and shared usage of external libraries.
 core = 7.x
 files[] = tests/libraries.test
+; We use format_string() in libraries_replace_filenames()
+dependencies[] = system (>=7.9)
diff --git a/libraries.module b/libraries.module
index c67ce79..bed0709 100644
--- a/libraries.module
+++ b/libraries.module
@@ -311,6 +311,58 @@ function libraries_detect_dependencies(&$library, $version = NULL, $variant = NU
 }
 
 /**
+ * Library pre-load callback to replace the version and variant in filenames.
+ *
+ * This callback allows to specify a filename as e.g.
+ * example-!version-!variant.js in hook_libraries_info(). It turns that into
+ * e.g. example-1.2.3-minified.js before loading the library.
+ *
+ * @param $library
+ *   An associative array of library information or a part of it, passed by
+ *   reference.
+ * @param $version
+ *   If the library information belongs to a specific version, the version
+ *   string. NULL otherwise.
+ * @param $variant
+ *   If the library information belongs to a specific variant, the variant name.
+ *   NULL otherwise.
+ *
+ * @see libraries_invoke()
+ */
+function libraries_replace_filenames(&$library, $version = NULL, $variant = NULL) {
+  // Both the 'files' property and the 'integration files' property contain file
+  // declarations, and we want to replace both.
+  $file_types = array();
+  if (isset($library['files'])) {
+    $file_types[] = &$library['files'];
+  }
+  if (isset($library['integration files'])) {
+    // Integration files are additionally keyed by module.
+    foreach ($library['integration files'] as &$integration_files) {
+      $file_types[] = &$integration_files;
+    }
+  }
+  foreach ($file_types as &$files) {
+    // Go through all supported types of files.
+    foreach (array('js', 'css', 'php') as $type) {
+      if (isset($files[$type])) {
+        foreach ($files[$type] as $old => $options) {
+          unset($files[$type][$old]);
+
+          $args = array('!version' => $library['version']);
+          // A library can be loaded without specifying a variant.
+          if (isset($library['variant'])) {
+            $args['!variant'] = $library['variant'];
+          }
+          $new = format_string($old, $args);
+          $files[$type][$new] = $options;
+        }
+      }
+    }
+  }
+}
+
+/**
  * Returns information about registered libraries.
  *
  * The returned information is unprocessed; i.e., as registered by modules.
@@ -589,6 +641,8 @@ function libraries_load($name, $variant = NULL) {
       // of the library files below.
       $library['variants'] += array($variant => array('installed' => FALSE));
       $library = array_merge($library, $library['variants'][$variant]);
+      // Make the variant available to 'pre-load' and 'post-load' callbacks.
+      $library['variant'] = $variant;
     }
     // Regardless of whether a specific variant was requested or not, there can
     // only be one variant of a library within a single request.
diff --git a/tests/libraries.test b/tests/libraries.test
index c361bcd..1675077 100644
--- a/tests/libraries.test
+++ b/tests/libraries.test
@@ -122,6 +122,24 @@ class LibrariesTestCase extends DrupalWebTestCase {
     $this->verbose('Actual:<br>' . $library['error message']);
     $this->assertEqual($library['error message'], $error_message, 'Correct error message for an incompatible dependency');
 
+    // Test libraries_replace_filename().
+    $library = array(
+      'version' => '1',
+      'files' => array('js' => array('example-!version.js' => array())),
+    );
+    libraries_replace_filenames($library);
+    $this->verbose(key($library['files']['js']));
+    $this->assertEqual(key($library['files']['js']), 'example-1.js', 'libraries_replace_filename() replaces the version correctly.');
+    $library = array(
+      'version' => '1',
+      'variant' => 'variant-1',
+      'files' => array('js' => array('example-!variant.js' => array())),
+    );
+    libraries_replace_filenames($library);
+    $this->verbose(var_export($library['files'], TRUE));
+    $this->assertEqual(key($library['files']['js']), 'example-variant-1.js', 'libraries_replace_filename() replaces the variant correctly.');
+
+
     // Test that library information is found correctly.
     $expected = array(
       'name' => 'Example files',
@@ -340,6 +358,7 @@ class LibrariesTestCase extends DrupalWebTestCase {
     $expected['info callback'] = 'applied (version 1, variant example_variant)';
     $expected['pre-detect callback'] = 'applied (version 1, variant example_variant)';
     $expected['post-detect callback'] = 'applied (variant example_variant)';
+    $expected['variant'] = 'example_variant';
     $library = libraries_load('example_callback', 'example_variant');
     $this->verbose('Expected:<pre>' . var_export($expected, TRUE) . '</pre>');
     $this->verbose('Actual:<pre>' . var_export($library, TRUE) . '</pre>');
