diff --git a/src/applications/files/management/PhabricatorFilesManagementMigrateWorkflow.php b/src/applications/files/management/PhabricatorFilesManagementMigrateWorkflow.php
--- a/src/applications/files/management/PhabricatorFilesManagementMigrateWorkflow.php
+++ b/src/applications/files/management/PhabricatorFilesManagementMigrateWorkflow.php
@@ -46,10 +46,44 @@
             'name'      => 'names',
             'wildcard'  => true,
           ),
+          array(
+            'name' => 'from-engine',
+            'param' => 'engine',
+            'help' => pht('Migrate files from the named storage engine.'),
+          ),
+          array(
+            'name' => 'local-disk-source',
+            'param' => 'path',
+            'help' => pht(
+              'When migrating from a local disk source, use the specified '.
+              'path as the root directory.'),
+          ),
         ));
   }
 
   public function execute(PhutilArgumentParser $args) {
+
+    // See T13306. This flag allows you to import files from a backup of
+    // local disk storage into some other engine. When the caller provides
+    // the flag, we override the local disk engine configuration and treat
+    // it as though it is configured to use the specified location.
+
+    $local_disk_source = $args->getArg('local-disk-source');
+    if (strlen($local_disk_source)) {
+      $path = Filesystem::resolvePath($local_disk_source);
+      try {
+        Filesystem::assertIsDirectory($path);
+      } catch (FilesystemException $ex) {
+        throw new PhutilArgumentUsageException(
+          pht(
+            'The "--local-disk-source" argument must point to a valid, '.
+            'readable directory on local disk.'));
+      }
+
+      $env = PhabricatorEnv::beginScopedEnv();
+      $env->overrideEnvConfig('storage.local-disk.path', $path);
+    }
+
     $target_key = $args->getArg('engine');
     if (!$target_key) {
       throw new PhutilArgumentUsageException(
diff --git a/src/applications/files/management/PhabricatorFilesManagementWorkflow.php b/src/applications/files/management/PhabricatorFilesManagementWorkflow.php
--- a/src/applications/files/management/PhabricatorFilesManagementWorkflow.php
+++ b/src/applications/files/management/PhabricatorFilesManagementWorkflow.php
@@ -4,23 +4,48 @@
   extends PhabricatorManagementWorkflow {
 
   protected function buildIterator(PhutilArgumentParser $args) {
+    $viewer = $this->getViewer();
     $names = $args->getArg('names');
 
-    if ($args->getArg('all')) {
-      if ($names) {
-        throw new PhutilArgumentUsageException(
-          pht(
-            'Specify either a list of files or `%s`, but not both.',
-            '--all'));
-      }
-      return new LiskMigrationIterator(new PhabricatorFile());
+    $is_all = $args->getArg('all');
+    $from_engine = $args->getArg('from-engine');
+
+    $any_constraint = ($from_engine || $names);
+
+    if (!$is_all && !$any_constraint) {
+      throw new PhutilArgumentUsageException(
+        pht(
+          'Use "--all" to migrate all files, or choose files to migrate '.
+          'with "--names" or "--from-engine".'));
+    }
+
+    if ($is_all && $any_constraint) {
+      throw new PhutilArgumentUsageException(
+        pht(
+          'You can not migrate all files with "--all" and also migrate only '.
+          'a subset of files with "--from-engine" or "--names".'));
     }
 
+    // If we're migrating specific named files, convert the names into IDs
+    // first.
+    $ids = null;
     if ($names) {
-      return $this->loadFilesWithNames($names);
+      $files = $this->loadFilesWithNames($names);
+      $ids = mpull($files, 'getID');
+    }
+
+    $query = id(new PhabricatorFileQuery())
+      ->setViewer($viewer);
+
+    if ($ids) {
+      $query->withIDs($ids);
+    }
+
+    if ($from_engine) {
+      $query->withStorageEngines(array($from_engine));
     }
 
-    return null;
+    return new PhabricatorQueryIterator($query);
   }
 
   protected function loadFilesWithNames(array $names) {
@@ -36,7 +61,7 @@
       if (empty($files[$name])) {
         throw new PhutilArgumentUsageException(
           pht(
-            "No file '%s' exists!",
+            'No file "%s" exists.',
             $name));
       }
     }
diff --git a/src/applications/files/query/PhabricatorFileQuery.php b/src/applications/files/query/PhabricatorFileQuery.php
--- a/src/applications/files/query/PhabricatorFileQuery.php
+++ b/src/applications/files/query/PhabricatorFileQuery.php
@@ -19,6 +19,7 @@
   private $needTransforms;
   private $builtinKeys;
   private $isBuiltin;
+  private $storageEngines;
 
   public function withIDs(array $ids) {
     $this->ids = $ids;
@@ -137,6 +138,11 @@
       $ngrams);
   }
 
+  public function withStorageEngines(array $engines) {
+    $this->storageEngines = $engines;
+    return $this;
+  }
+
   public function showOnlyExplicitUploads($explicit_uploads) {
     $this->explicitUploads = $explicit_uploads;
     return $this;
@@ -469,6 +475,13 @@
       }
     }
 
+    if ($this->storageEngines !== null) {
+      $where[] = qsprintf(
+        $conn,
+        'storageEngine IN (%Ls)',
+        $this->storageEngines);
+    }
+
     return $where;
   }