diff --git a/fish/destpaths.c b/fish/destpaths.c
index ad57efd..03e3ef2 100644
--- a/fish/destpaths.c
+++ b/fish/destpaths.c
@@ -55,11 +55,6 @@
 
 int complete_dest_paths = 1;
 
-struct word {
-  char *name;
-  int is_dir;
-};
-
 #ifdef HAVE_LIBREADLINE
 static void
 free_words (struct word *words, size_t nr_words)
@@ -79,6 +74,72 @@ compare_words (const void *vp1, const void *vp2)
   const struct word *w2 = (const struct word *) vp2;
   return strcmp (w1->name, w2->name);
 }
+
+/* List content of a directory specified by 'text' argument.
+ * Store the directory entries themselves into structure
+ * provided as 'ws' argument, and count of the items found
+ * into 'nr_ws' argument.
+ */
+void
+list_directory_entries (const char *text, struct word **ws, size_t *nr_ws)
+{
+  struct word *words = NULL;
+  size_t nr_words = 0;
+
+  /* If we've got a partial path already, we need to list everything
+   * in that directory, otherwise list everything in /
+   */
+  char *p, *dir;
+  struct guestfs_dirent_list *dirents;
+
+  p = strrchr (text, '/');
+  dir = p && p > text ? strndup (text, p - text) : strdup ("/");
+  if (dir) {
+    dirents = guestfs_readdir (g, dir);
+
+    /* Prepend directory to names before adding them to the list
+     * of words.
+     */
+    if (dirents) {
+      size_t i;
+
+      for (i = 0; i < dirents->len; ++i) {
+        int err;
+
+        if (STRNEQ (dirents->val[i].name, ".") &&
+            STRNEQ (dirents->val[i].name, "..")) {
+          if (STREQ (dir, "/"))
+            err = asprintf (&p, "/%s", dirents->val[i].name);
+          else
+            err = asprintf (&p, "%s/%s", dir, dirents->val[i].name);
+          if (err >= 0) {
+            if (!xalloc_oversized (nr_words+1, sizeof (struct word))) {
+              struct word *w;
+
+              w = realloc (words, sizeof (struct word) * (nr_words+1));
+              if (w == NULL) {
+                free_words (words, nr_words);
+                words = NULL;
+                nr_words = 0;
+              }
+              else {
+                words = w;
+                words[nr_words].name = p;
+                words[nr_words].is_dir = dirents->val[i].ftyp == 'd';
+                nr_words++;
+              }
+            }
+          }
+        }
+      }
+
+      guestfs_free_dirent_list (dirents);
+    }
+  }
+  /* Save the generated content back to the original arguments. */
+  *ws = words;
+  *nr_ws = nr_words;
+}
 #endif
 
 char *
@@ -150,58 +211,8 @@ complete_dest_paths_generator (const char *text, int state)
       APPEND_STRS_AND_FREE;
     }
 
-    if (len < 1 || text[0] == '/') {
-      /* If we've got a partial path already, we need to list everything
-       * in that directory, otherwise list everything in /
-       */
-      char *p, *dir;
-      struct guestfs_dirent_list *dirents;
-
-      p = strrchr (text, '/');
-      dir = p && p > text ? strndup (text, p - text) : strdup ("/");
-      if (dir) {
-        dirents = guestfs_readdir (g, dir);
-
-        /* Prepend directory to names before adding them to the list
-         * of words.
-         */
-        if (dirents) {
-          size_t i;
-
-          for (i = 0; i < dirents->len; ++i) {
-            int err;
-
-            if (STRNEQ (dirents->val[i].name, ".") &&
-                STRNEQ (dirents->val[i].name, "..")) {
-              if (STREQ (dir, "/"))
-                err = asprintf (&p, "/%s", dirents->val[i].name);
-              else
-                err = asprintf (&p, "%s/%s", dir, dirents->val[i].name);
-              if (err >= 0) {
-                if (!xalloc_oversized (nr_words+1, sizeof (struct word))) {
-                  struct word *w;
-
-                  w = realloc (words, sizeof (struct word) * (nr_words+1));
-                  if (w == NULL) {
-                    free_words (words, nr_words);
-                    words = NULL;
-                    nr_words = 0;
-                  }
-                  else {
-                    words = w;
-                    words[nr_words].name = p;
-                    words[nr_words].is_dir = dirents->val[i].ftyp == 'd';
-                    nr_words++;
-                  }
-                }
-              }
-            }
-          }
-
-          guestfs_free_dirent_list (dirents);
-        }
-      }
-    }
+    if (len < 1 || text[0] == '/')
+      list_directory_entries (text, &words, &nr_words);
 
     /* else ...  In theory we could complete other things here such as VG
      * names.  At the moment we don't do that.
diff --git a/fish/fish.h b/fish/fish.h
index df22e34..1a56dd7 100644
--- a/fish/fish.h
+++ b/fish/fish.h
@@ -61,6 +61,11 @@ extern char **do_completion (const char *text, int start, int end);
 
 /* in destpaths.c */
 extern int complete_dest_paths;
+struct word {
+  char *name;
+  int is_dir;
+};
+extern void list_directory_entries (const char *text, struct word **ws, size_t *nr_ws);
 extern char *complete_dest_paths_generator (const char *text, int state);
 
 /* in events.c */
