在Qt应用程序中获取当前工作目录

83
我正在使用Qt库编写C++程序。我的主目录bin文件夹中有一个符号链接指向可执行文件。我希望程序的当前工作目录是终端所在的目录(即pwd命令的结果)。我看到了QDir::currentPath()函数,但它返回的是二进制文件所在的目录。如何找到我的当前工作目录呢?

1
QDir的默认构造函数会给出相同的结果吗? - cmannett85
2
是的:QDir dir; Cout << dir.absolutePath() << flush; 返回可执行文件所在的目录。 - Geoffroy
1
QDir::currentPath()和dir.absolutePath()都返回命令行的当前目录。 - Flint
5个回答

118

刚刚测试了一下,QDir::currentPath()确实返回了我调用可执行文件的路径。

而且一个符号链接并不存在。如果你从该路径执行一个exe文件,那么实际上是从符号链接指向的路径执行它。


65

12
如果我读取文档,这会给出可执行文件所在的目录。但我想要的是可执行文件所在被调用的目录。 - Geoffroy
3
这通常会起作用,但并非每个人都会使用QCoreApplication。例如,我的QTest就无法使用它。 - kayleeFrye_onDeck
使用applicationDirPath的问题在于不同操作系统返回的路径可能会有所不同,在Mac上应用程序会打包在file.app文件中,当调用applicationDirPath时,您会得到文件位置和打包在file.app中的文件夹。 - SPlatten
这不是一个工作目录。 - undefined

10

补充KaZ的回答,每当我制作QML应用程序时,我倾向于将此添加到主要的C++文件中

#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QStandardPaths>

int main(int argc, char *argv[])
{
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;

// get the applications dir path and expose it to QML 

QUrl appPath(QString("%1").arg(app.applicationDirPath()));
engine.rootContext()->setContextProperty("appPath", appPath);


// Get the QStandardPaths home location and expose it to QML 
QUrl userPath;
   const QStringList usersLocation = QStandardPaths::standardLocations(QStandardPaths::HomeLocation);
   if (usersLocation.isEmpty())
       userPath = appPath.resolved(QUrl("/home/"));
   else
      userPath = QString("%1").arg(usersLocation.first());
   engine.rootContext()->setContextProperty("userPath", userPath);

   QUrl imagePath;
      const QStringList picturesLocation = QStandardPaths::standardLocations(QStandardPaths::PicturesLocation);
      if (picturesLocation.isEmpty())
          imagePath = appPath.resolved(QUrl("images"));
      else
          imagePath = QString("%1").arg(picturesLocation.first());
      engine.rootContext()->setContextProperty("imagePath", imagePath);

      QUrl videoPath;
      const QStringList moviesLocation = QStandardPaths::standardLocations(QStandardPaths::MoviesLocation);
      if (moviesLocation.isEmpty())
          videoPath = appPath.resolved(QUrl("./"));
      else
          videoPath = QString("%1").arg(moviesLocation.first());
      engine.rootContext()->setContextProperty("videoPath", videoPath);

      QUrl homePath;
      const QStringList homesLocation = QStandardPaths::standardLocations(QStandardPaths::HomeLocation);
      if (homesLocation.isEmpty())
          homePath = appPath.resolved(QUrl("/"));
      else
          homePath = QString("%1").arg(homesLocation.first());
      engine.rootContext()->setContextProperty("homePath", homePath);

      QUrl desktopPath;
      const QStringList desktopsLocation = QStandardPaths::standardLocations(QStandardPaths::DesktopLocation);
      if (desktopsLocation.isEmpty())
          desktopPath = appPath.resolved(QUrl("/"));
      else
          desktopPath = QString("%1").arg(desktopsLocation.first());
      engine.rootContext()->setContextProperty("desktopPath", desktopPath);

      QUrl docPath;
      const QStringList docsLocation = QStandardPaths::standardLocations(QStandardPaths::DocumentsLocation);
      if (docsLocation.isEmpty())
          docPath = appPath.resolved(QUrl("/"));
      else
          docPath = QString("%1").arg(docsLocation.first());
      engine.rootContext()->setContextProperty("docPath", docPath);


      QUrl tempPath;
      const QStringList tempsLocation = QStandardPaths::standardLocations(QStandardPaths::TempLocation);
      if (tempsLocation.isEmpty())
          tempPath = appPath.resolved(QUrl("/"));
      else
          tempPath = QString("%1").arg(tempsLocation.first());
      engine.rootContext()->setContextProperty("tempPath", tempPath);
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
return app.exec();
}

在QML中使用它

....
........
............
Text{
text:"This is the applications path: " + appPath
+ "\nThis is the users home directory: " + homePath
+ "\nThis is the Desktop path: " desktopPath;
}

现在有一个 StandardPaths QML 模块:https://doc.qt.io/qt-5/qml-qt-labs-platform-standardpaths.html - Jean-Michaël Celerier

4

感谢RedX和Kaz的回答。我不明白为什么它会给出exe文件的路径。我找到了另一种方法来做这件事:

QString pwd("");
char * PWD;
PWD = getenv ("PWD");
pwd.append(PWD);
cout << "Working directory : " << pwd << flush;

它不如单行代码那样优雅...但对我来说有效。


3
我也可以使用 QFileInfo(".").absolutePath() 获取它。 - crgarridos

4
我正在Windows下运行Qt 5.5,发现QDir的默认构造函数似乎会选择当前工作目录,而不是应用程序目录。
我不确定getenv PWD在跨平台时是否有效,而且我认为它被设置为当shell启动应用程序时的当前工作目录,并不包括应用程序本身所做的任何工作目录更改(这可能是为什么OP看到这种行为的原因)。
因此,我想添加一些其他方法,应该可以给出当前工作目录(而不是应用程序的二进制位置)。
// using where a relative filename will end up
QFileInfo fi("temp");
cout << fi.absolutePath() << endl;

// explicitly using the relative name of the current working directory
QDir dir(".");
cout << dir.absolutePath() << endl;

谢谢您的建议,Mark。但是我已经在 Linux 系统下使用 Qt5.3.2 对两个解决方案进行了测试,并且两者都给出了二进制文件位置... - Geoffroy
Qt 5.8 在 Windows 上会在两种情况下都给出工作目录。 - Tomas Tintera

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接