diff --git a/src/windeployqt/main.cpp b/src/windeployqt/main.cpp
index dc57f340bd42219e6077ca4bb1917e098fd8cd12..23b64be3c3bbbb61b35ffddf9190c1831622aceb 100644
--- a/src/windeployqt/main.cpp
+++ b/src/windeployqt/main.cpp
@@ -746,8 +746,8 @@ static DeployResult deploy(const Options &options,
             }
             if (optVerboseLevel >= 1) {
                 std::fputs("QML imports:\n", stdout);
-                foreach (const QString &mod, qmlScanResult.modulesDirectories)
-                    std::printf("  %s\n",  qPrintable(QDir::toNativeSeparators(mod)));
+                foreach (const QmlImportScanResult::Module &mod, qmlScanResult.modules)
+                    std::printf("  '%s' %s\n", qPrintable(mod.name), qPrintable(QDir::toNativeSeparators(mod.sourcePath)));
                 if (optVerboseLevel >= 2) {
                 std::fputs("QML plugins:\n", stdout);
                 foreach (const QString &p, qmlScanResult.plugins)
@@ -851,8 +851,14 @@ static DeployResult deploy(const Options &options,
     if (options.quickImports && (usesQuick1 || usesQml2)) {
         const QmlDirectoryFileEntryFunction qmlFileEntryFunction(options.platform, isDebug);
         if (usesQml2) {
-            foreach (const QString &module, qmlScanResult.modulesDirectories) {
-                if (!updateFile(module, qmlFileEntryFunction, options.directory, options.updateFileFlags, options.json, errorMessage))
+            foreach (const QmlImportScanResult::Module &module, qmlScanResult.modules) {
+                const QString installPath = module.installPath(options.directory);
+                if (optVerboseLevel > 1)
+                    std::printf("Installing: '%s' from %s to %s\n",
+                                qPrintable(module.name), qPrintable(module.sourcePath), qPrintable(QDir::toNativeSeparators(installPath)));
+                if (installPath != options.directory && !createDirectory(installPath, errorMessage))
+                    return result;
+                if (!updateFile(module.sourcePath, qmlFileEntryFunction, installPath, options.updateFileFlags, options.json, errorMessage))
                     return result;
             }
         } // Quick 2
diff --git a/src/windeployqt/qmlutils.cpp b/src/windeployqt/qmlutils.cpp
index 1a2ea60b438b6449e0c7a8397bd0ffcb24513f82..aef73636493c2a47b875c7b01bbd126651b47f6a 100644
--- a/src/windeployqt/qmlutils.cpp
+++ b/src/windeployqt/qmlutils.cpp
@@ -52,6 +52,41 @@
 
 QT_BEGIN_NAMESPACE
 
+// Return the relative install path, that is, for example for
+// module "QtQuick.Controls.Styles" in "path/qtbase/qml/QtQuick/Controls/Styles.3"
+// --> "QtQuick/Controls" suitable for updateFile() (cp -r semantics).
+QString QmlImportScanResult::Module::relativeInstallPath() const
+{
+    const QChar dot = QLatin1Char('.');
+    const QChar slash = QLatin1Char('/');
+
+    // Find relative path by module name.
+    if (!name.contains(dot))
+        return QString(); // "QtQuick.2" -> flat folder.
+    QString result = sourcePath;
+    QString pathComponent = name;
+    pathComponent.replace(dot, slash);
+    const int pos = result.lastIndexOf(pathComponent);
+    if (pos < 0)
+        return QString();
+    result.remove(0, pos);
+    // return base name.
+    const int lastSlash = result.lastIndexOf(slash);
+    if (lastSlash >= 0)
+        result.truncate(lastSlash);
+    return result;
+}
+
+QString QmlImportScanResult::Module::installPath(const QString &root) const
+{
+    QString result = root;
+    const QString relPath = relativeInstallPath();
+    if (!relPath.isEmpty())
+        result += QLatin1Char('/');
+    result += relPath;
+    return result;
+}
+
 static QString qmlDirectoryRecursion(Platform platform, const QString &path)
 {
     QDir dir(path);
@@ -119,7 +154,11 @@ QmlImportScanResult runQmlImportScanner(const QString &directory, const QString
         if (object.value(QStringLiteral("type")).toString() == QLatin1String("module")) {
             const QString path = object.value(QStringLiteral("path")).toString();
             if (!path.isEmpty()) {
-                result.modulesDirectories.append(path);
+                QmlImportScanResult::Module module;
+                module.name = object.value(QStringLiteral("name")).toString();
+                module.className = object.value(QStringLiteral("classname")).toString();
+                module.sourcePath = path;
+                result.modules.append(module);
                 findFileRecursion(QDir(path), Platform(platform), debug, &result.plugins);
             }
         }
@@ -128,11 +167,20 @@ QmlImportScanResult runQmlImportScanner(const QString &directory, const QString
     return result;
 }
 
+static inline bool contains(const QList<QmlImportScanResult::Module> &modules, const QString &name)
+{
+    foreach (const QmlImportScanResult::Module &m, modules) {
+        if (m.name == name)
+            return true;
+    }
+    return false;
+}
+
 void QmlImportScanResult::append(const QmlImportScanResult &other)
 {
-    foreach (const QString &module, other.modulesDirectories) {
-        if (!modulesDirectories.contains(module))
-            modulesDirectories.append(module);
+    foreach (const QmlImportScanResult::Module &module, other.modules) {
+        if (!contains(modules, module.name))
+            modules.append(module);
     }
     foreach (const QString &plugin, other.plugins) {
         if (!plugins.contains(plugin))
diff --git a/src/windeployqt/qmlutils.h b/src/windeployqt/qmlutils.h
index ea8c7747da40925c171a54932bbac907db19c48e..1752d2717099406e47079161778322d549c18c75 100644
--- a/src/windeployqt/qmlutils.h
+++ b/src/windeployqt/qmlutils.h
@@ -49,11 +49,20 @@ QT_BEGIN_NAMESPACE
 QString findQmlDirectory(int platform, const QString &startDirectoryName);
 
 struct QmlImportScanResult {
+    struct Module {
+        QString relativeInstallPath() const;
+        QString installPath(const QString &root) const;
+
+        QString name;
+        QString className;
+        QString sourcePath;
+    };
+
     QmlImportScanResult() : ok(false) {}
     void append(const QmlImportScanResult &other);
 
     bool ok;
-    QStringList modulesDirectories;
+    QList<Module> modules;
     QStringList plugins;
 };