Skip to content

Instantly share code, notes, and snippets.

@fbudin69500
Last active December 14, 2015 15:59
Show Gist options
  • Save fbudin69500/5112208 to your computer and use it in GitHub Desktop.
Save fbudin69500/5112208 to your computer and use it in GitHub Desktop.
ctkUtils.cpp does not normally copy broken symlinks when recursively copying a directory. These couple lines modify its behavior so that it actually copies those links. Those links can be useful for example when one needs to "insall" symlinks on a target computer, but does not have control over that computer to select the path at install time. I…
foreach(const QFileInfo &info, srcDir.entryInfoList(QDir::Dirs | QDir::Files | QDir::NoDotAndDotDot|QDir::System))
{
QString srcItemPath = srcPath + "/" + info.fileName();
QString dstItemPath = dstPath + "/" + info.fileName();
if (info.isDir())
{
std::cout<< "Directory" << std::endl;
}
else if (info.isFile())
{
std::cout<< "File" << std::endl ;
if (!QFile::copy(srcItemPath, dstItemPath))
{
return false;
}
}
else if (info.isSymLink() )
//For broken symbolic links. We take care of them only after. If the symlink points to a file or a directory,
//we prefer to let the system handle it as a file or a directory and not as a symlink. This should allow backward compatibility
{
std::cout<< "SymLink" << std::endl ;
//we need to change working directories to get the correct link path given by Qt if the link was relative
std::string fileNamePath = itksys::SystemTools::GetFilenamePath( info.absoluteFilePath().toStdString().c_str() ) ;
std::string cwd = itksys::SystemTools::GetCurrentWorkingDirectory() ;
itksys::SystemTools::ChangeDirectory( fileNamePath.c_str() ) ;
//We get the absolute link path, but we want the relative one
QString linkAbsolutePath = QString( fileNamePath.c_str() ) + "/" + info.fileName() ;
QFileInfo fi( linkAbsolutePath ) ;
QString target = fi.symLinkTarget() ;
itksys::SystemTools::ChangeDirectory( cwd.c_str() ) ;
//by comparing the link original path and the absolute path it points to, we get the relative link path
std::string relativePath = itksys::SystemTools::RelativePath( fileNamePath.c_str() , target.toStdString().c_str() ) ;
//We set the value of the link we want to create to the relative path we just got
QFile currentFile( relativePath.c_str() ) ;
//We create the link in the destination folder
currentFile.link( dstItemPath ) ;
}
else
{
std::cout<<"Other" << std::endl ;
}
@finetjul
Copy link

To make the code fully Qt/CTK compatible (no itksys), here are some useful functions:
QDir::relativeFilePath
QDir::setCurrent
QDir::currentPath
To construct file paths, prefer QFileInfo fi(QDir, QString) instead of doing string concatenation (see here )

@finetjul
Copy link

Email from 03/08/2013:

That seems like an interesting feature to add to ctkUtils, could you tweak your code in order to make a pull request with it?
I can think of:
bool ctk::copyDirRecursively(const QString &srcPath, const QString &dstPath, CopyOptions options = SomeDefaultFlags)
where CopyOptions would be a new QFLAGS. (for eg, I can think of options such as ContinueOnError, RedirectSymLinks...)

@fbudin69500
Copy link
Author

Julien, the following lines:

QString srcItemPath = srcPath + "/" + info.fileName();
QString dstItemPath = dstPath + "/" + info.fileName();

are already in CTK. I guess those lines should be replaced by QFileInfo fi(QDir, QString) too.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment