web-dev-qa-db-fra.com

Git Bash Shell ne parvient pas à créer des liens symboliques

Lorsque j'essaie de créer un lien symbolique à partir du shell Git Bash, il échoue à chaque fois:

$ ln -s /c/Users/bzisad0/Work testlink
ln: creating symbolic link `testlink' to `/c/Users/bzisad0/Work': Permission denied

La seule chose qu'il fait, en plus de donner le message d'erreur, est de créer un répertoire vide nommé (dans ce cas) testlink.

Je ne vois aucun problème avec l'exécutable ln. Par exemple, il est la propriété de moi et marqué comme exécutable:

$ which ln
/bin/ln

$ ls -hal /bin/ln
-rwxr-xr-x    1 BZISAD0  Administ      71k Sep  5 11:55 /bin/ln

Je possède également le répertoire actuel (~, qui est /c/Users/bzisad0):

$ ls -dhal .
drwxr-xr-x  115 BZISAD0  Administ      40k Sep  5 12:23 .

J'ai des droits administratifs et j'ai essayé d'ouvrir le shell Git Bash avec "Exécuter en tant qu'administrateur", mais cela ne fait aucune différence. 

J'ai essayé d'ouvrir les propriétés Windows pour ln.exe et de définir le niveau de privilège sur "Exécuter ce programme en tant qu'administrateur", mais cela n'aide pas.

Je suis allé dans les propriétés de sécurité -> avancées de Windows et je me suis fait propriétaire (plutôt que du groupe des administrateurs), mais cela ne règle rien non plus.

Je suis à perte. Je ne sais pas si ce message d'erreur vient finalement de ln, de Bash ou de Windows, ou comment je pourrais éventuellement ne pas avoir l'autorisation. Comment puis-je aller au fond des choses?

54
iconoclast

Il est possible, mais extrêmement gênant, de créer un lien symbolique dans MSYSGIT.

Premièrement, nous devons nous assurer que nous sommes sur Windows. Voici un exemple de fonction pour vérifier cela:

windows() { [[ -n "$WINDIR" ]]; }

Maintenant, nous ne pouvons pas faire cmd /C, car MSYSGIT forniquera avec cet argument et le transformera en C:. En outre, ne soyez pas tenté d'utiliser /K, cela ne fonctionne que si vous n'avez pas de lecteur K:.

Ainsi, bien qu'elle remplace cette valeur sur les arguments du programme, elle ne le sera pas sur heredocs. Nous pouvons utiliser ceci à notre avantage:

if windows; then
    cmd <<< "mklink /D \"${link%/}\" \"${target%/}\"" > /dev/null
else
    ln -s "$target" "$link"
fi

Aussi: notez que j'ai inclus /D parce que les liens symboliques du répertoire m'intéressent uniquement; Windows a cette distinction. Avec beaucoup d'effort, vous pourriez écrire une fonction ln() { ... } qui englobe l'API Windows et constitue une solution complète, mais c'est un exercice pour le lecteur.


Edit: En guise de remerciement pour la réponse acceptée, voici une fonction plus complète.

# We still need this.
windows() { [[ -n "$WINDIR" ]]; }

# Cross-platform symlink function. With one parameter, it will check
# whether the parameter is a symlink. With two parameters, it will create
# a symlink to a file or directory, with syntax: link $linkname $target
link() {
    if [[ -z "$2" ]]; then
        # Link-checking mode.
        if windows; then
            fsutil reparsepoint query "$1" > /dev/null
        else
            [[ -h "$1" ]]
        fi
    else
        # Link-creation mode.
        if windows; then
            # Windows needs to be told if it's a directory or not. Infer that.
            # Also: note that we convert `/` to `\`. In this case it's necessary.
            if [[ -d "$2" ]]; then
                cmd <<< "mklink /D \"$1\" \"${2//\//\\}\"" > /dev/null
            else
                cmd <<< "mklink \"$1\" \"${2//\//\\}\"" > /dev/null
            fi
        else
            # You know what? I think ln's parameters are backwards.
            ln -s "$2" "$1"
        fi
    fi
}

Notez également quelques points:

  1. Je viens d'écrire ceci et de l'essayer brièvement sur Win7 et Ubuntu. Essayez-le d'abord si vous êtes à partir de 2015 et utilisez Windows 9.
  2. NTFS a des points d'analyse et des points de jonction. J'ai choisi des points d'analyse car il s'agit davantage d'un lien symbolique réel et fonctionne pour les fichiers ou les répertoires, mais les points de jonction auraient l'avantage d'être une solution utilisable dans XP, à l'exception du cas des répertoires.
  3. Certains systèmes de fichiers, ceux FAT en particulier, ne supportent pas les liens symboliques. Les versions Windows modernes ne prennent plus en charge le démarrage à partir d’elles, mais Windows et Linux peuvent les monter.

Fonction bonus: supprimer un lien.

# Remove a link, cross-platform.
rmlink() {
    if windows; then
        # Again, Windows needs to be told if it's a file or directory.
        if [[ -d "$1" ]]; then
            rmdir "$1";
        else
            rm "$1"
        fi
    else
        rm "$1"
    fi
}
56
Camilo Martin

Une solution de contournement consiste à exécuter mklink à partir de Bash. Cela vous permet également de créer un lien symbolique ou une jonction

Prenez soin d’envoyer la commande mklink en tant qu’argument unique à cmd ...

cmd  /c "mklink link target"

Voici les options pour mklink ...

$ cmd /c mklink
   Creates a symbolic link.

MKLINK [[/D] | [/H] | [/J]] Link Target

    /D      Creates a directory symbolic link.  Default is a file
            symbolic link.
    /H      Creates a hard link instead of a symbolic link.
    /J      Creates a Directory Junction.
    Link    specifies the new symbolic link name.
    Target  specifies the path (relative or absolute) that the new link
            refers to.

Si vous souhaitez plutôt créer des liens via une interface graphique ... Je recommande Link Shell Extension qui est un plug-in de l'explorateur Windows permettant de créer des liens symboliques, des liens physiques, des jonctions et des points de montage en volume. Je l'utilise depuis des années!

Les liens symboliques peuvent vous sauver la vie si vous avez un lecteur SSD plus petit sur votre lecteur système C: et que vous devez créer un lien symbolique vers des dossiers surchargés qui ne nécessitent pas nécessairement d'être en mode SSD sur d'autres lecteurs. J'utilise le répertoire libre WinDirStat pour trouver les réserveurs d'espace disque. 

16
Tony O'Hagan

Je crois que la ln fournie avec msysGit essaie simplement de copier ses arguments, plutôt que de manipuler des liens. En effet, les liens fonctionnent uniquement (en quelque sorte) sur les systèmes de fichiers NTFS, et l’équipe MSYS ne souhaitait pas réimplémenter ln.

Voir, par exemple, http://mingw.5.n7.nabble.com/symbolic-link-to-My-Documents-in-MSYS-td28492.html

14
Austin Hastings

Pour ma configuration, c'est Git pour Windows 2.11.0 installé sur Windows 8.1 export MSYS=winsymlinks:nativestrict fait l'affaire comme expliqué ici: https://github.com/git-for-windows/git/pull/156 Il est important de lancer Git Bash Shell en tant qu'administrateur, car sous Windows, seuls les administrateurs pouvaient créer les liens symboliques . Ainsi, pour que tar -xf fonctionne et crée les liens symboliques requis:

  1. Lancer Git Bash Shell en tant qu'administrateur
  2. Exécuter export MSYS=winsymlinks:nativestrict
  3. Run tar
10
Mikhail Filimonov

Comme il s’agit d’un des principaux liens qui apparaissent lors de la création de liens symboliques dans Msys ou git bash, j’ai trouvé la réponse à ajouter set MSYS=winsymlinks:native lorsqu’appelez git-cmd.exe (je lance ConEmu) ou décommentez la même ligne dans le msys2_Shell.bat

2
swee lim

Étendre la réponse de Camilo Martin à l'utilisation du commutateur de paramètres/j pour Windows 10; sinon, l'appel retournera simplement "Vous ne disposez pas du privilège suffisant pour effectuer cette opération".

Cela fonctionne pour git bash 2.20.1.windows.1/MINGW64 (Windows 10) sans droits d’administrateur (si vous pouvez lire/écrire les deux/old/path et/link/path:

original_folder=$(cygpath -w "/old/path")
create_link_new_folder=$(cygpath -w "/link/path")
cmd <<< "mklink /j \"${create_link_new_folder}\" \"${original_folder}\"" > /dev/null
1
Oliver Zendel

Je préfère Powershell à CMD et je pensais partager la version powershell de ce logiciel.

Dans mon cas, il s'agit de créer des liens symboliques reliant le fichier ~ /.$ au fichier ~/dotfiles/$, Pour les configurations de fichiers points. J'ai mis cela dans un script .sh et l'ai exécuté avec git-bash:

powershell New-Item -ItemType SymbolicLink\
    -Path \$Home/.$file\
    -Target \$Home/dotfiles/$file
0
Christian Fosli