En C #, j'ai besoin de trouver le chemin réel d'un fichier / répertoire sous Linux qui pourrait se trouver de l'autre côté d'un lien symbolique.
J'ai trouvé la solution à cela sur Windows à Comment obtenir la cible d'un lien symbolique (ou Reparse Point) en utilisant .Net? , mais cela pour des raisons assez évidentes ne fonctionnera pas sous Linux. Je pourrais appeler readlink, mais il se peut que je doive souvent le faire et je détesterais passer tout ce temps à gérer des processus externes.
J'aimerais quelque chose comme ça:
/link -> /actual/path
Si le lien symbolique est quelque chose comme:
string GetFinalPathName(string inputPath);
Et j'appelle GetFinalPathName("/link/myfile.txt")
il devrait retourner "/actual/path/myfile.txt".
Comment puis-je trouver la cible d'un lien symbolique Linux en C #?
3 Réponses :
Je pense que vous devrez créer un projet C / C ++ natif qui exporte un wrapper pour la fonction Linux readlink (), puis utiliser l'appel de plate-forme pour l'appeler à partir de C #. Cela semble être la manière dont le CLR le gère. Malheureusement, je ne pense pas que vous puissiez simplement appeler leur implémentation: code CLR Unix ReadLink
J'ai découvert une solution.
Commencez avec le package nuget mono.posix-4.5:
https://www.nuget.org/packages/Mono.Posix-4.5/
Ensuite, la solution était simple:
return Mono.Unix.UnixPath.GetRealPath(path);
Plus d'informations sur Mono.Posix: Mono.Posix.NETStandard est plus à jour et prend en charge .NET Standard. Malgré l'espace de noms Mono, cela semble être la manière approuvée par Microsoft de passer des appels Posix / Unix. Détails dans ce numéro .
Bien que la bibliothèque NuGet Mono.Posix.NETStandard
puisse faire le travail, utilisez-la avec prudence. À mon avis, cela produit des résultats inattendus et contre-intuitifs. Vous trouverez ci-dessous quelques tests avec la sortie de GetRealPath()
et des fonctions similaires sur Max OSX Catalina (v.10.15.7).
Sur la base de ces tests, il semble que vous ne pouvez pas simplement fournir le chemin complet de GetRealPath()
ou d'autres fonctions et obtenir le chemin du fichier cible final avec les liens symboliques résolus en conséquence. Au lieu de cela, vous devez tester chaque dossier du chemin à l'aide de GetRealPath()
ou GetCompleteRealPath()
.
Depuis le terminal:
GetRealPath() => /Volumes/Mac HD/Users/Shared/existing.txt GetCompleteRealPath() => //Users/Shared/existing.txt GetCanonicalPath() => /Volumes/Mac HD/Users/Shared/existing.txt
À partir des tests C #:
Chemin d'entrée: /Volumes/Mac HD
<== c'est le volume racine
GetRealPath() => /Volumes/Mac HD/ GetCompleteRealPath() => / GetCanonicalPath() => /Volumes/Mac HD
Chemin d'entrée: /Volumes/Mac HD/
<== la barre oblique de fin produit des résultats inattendus
GetRealPath() => / GetCompleteRealPath() => / GetCanonicalPath() => /Volumes/Mac HD
Chemin d'entrée: /Volumes/Mac HD/Users/Shared/existing.txt
<== le fichier existant dans le volume lié par un lien symbolique donne "//" dans GetCompleteRealPath()
$ pwd /Volumes $ ls -l total 0 drwxr-xr-x 32 root wheel 1156 Oct 7 17:12 HD2 lrwxr-xr-x 1 root wheel 1 Nov 12 22:14 Mac HD -> /