webentwicklung-frage-antwort-db.com.de

Git Bash Shell kann keine symbolischen Links erstellen

Wenn ich versuche, einen symbolischen Link von der Git Bash-Shell aus zu erstellen, schlägt dies immer wieder fehl:

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

Neben der Fehlermeldung wird nur ein leeres Verzeichnis mit dem Namen (in diesem Fall) testlink erstellt.

Ich sehe kein Problem mit der ausführbaren Datei ln. Zum Beispiel gehört es mir und ist als ausführbar gekennzeichnet:

$ which ln
/bin/ln

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

Ich besitze auch das aktuelle Verzeichnis (~, das ist /c/Users/bzisad0):

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

Ich habe Administratorrechte und habe versucht, die Git Bash Shell mit "Als Administrator ausführen" zu öffnen, aber das macht keinen Unterschied. 

Ich habe versucht, die Windows-Eigenschaften für ln.exe zu öffnen und die Berechtigungsebene auf "Dieses Programm als Administrator ausführen" zu setzen. Dies hilft jedoch nicht.

Ich habe in den Eigenschaften "Sicherheit"> "Erweitert" in Windows gesucht und mich selbst (und nicht die Gruppe "Administratoren") zum Eigentümer gemacht.

Ich bin ratlos. Ich weiß nicht, ob diese Fehlermeldung letztendlich von ln, von Bash oder von Windows stammt oder wie mir möglicherweise die Berechtigung fehlt. Wie kann ich dem auf den Grund gehen?

54
iconoclast

Es ist möglich, wenn auch äußerst umständlich, in MSYSGIT einen Symlink zu erstellen.

Zunächst müssen wir sicherstellen, dass wir Windows verwenden. Hier ist eine Beispielfunktion, um das zu überprüfen:

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

Nun können wir cmd /C nicht ausführen, da MSYSGIT dieses Argument mit einem Argument umgehen und in C: umwandeln wird. Seien Sie auch nicht versucht, /K zu verwenden. Es funktioniert nur, wenn Sie kein K:-Laufwerk haben.

Es wird zwar diesen Wert in Programmargumenten ersetzen, nicht aber in heredocs. Wir können das zu unserem Vorteil nutzen:

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

Beachten Sie auch, dass ich /D aufgenommen habe, da ich mich nur für Verzeichnis-Symlinks interessiere. Windows hat diesen Unterschied. Mit viel Aufwand könnten Sie eine ln() { ... }-Funktion schreiben, die die Windows-API umschließt und als vollständige Drop-In-Lösung dient, die dem Leser jedoch als Übung bleibt.


Bearbeiten: Als Dankeschön für die akzeptierte Antwort ist hier eine umfassendere Funktion.

# 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
}

Beachten Sie auch ein paar Dinge:

  1. Ich habe dies gerade geschrieben und kurz unter Win7 und Ubuntu getestet. Probieren Sie es zuerst aus, wenn Sie ab 2015 mit Windows 9 arbeiten.
  2. NTFS verfügt über Reparaturpunkte und Verbindungspunkte. Ich habe Reparse-Punkte gewählt, da es sich eher um einen echten Symlink handelt und für Dateien oder Verzeichnisse geeignet ist. Junction-Punkte haben jedoch den Vorteil, dass sie in XP eine verwendbare Lösung sind, es sei denn, es handelt sich lediglich um Verzeichnisse.
  3. Einige Dateisysteme, insbesondere die FAT, unterstützen keine Symlinks. Moderne Windows-Versionen unterstützen das Starten von ihnen nicht mehr, aber Windows und Linux können sie mounten.

Bonusfunktion: Link entfernen.

# 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

Eine Problemumgehung besteht darin, mklink von Bash aus auszuführen. Auf diese Weise können Sie auch ein Symlink oder eine Junction erstellen. 

Achten Sie darauf, den Befehl mklink als einzelnes Argument an cmd zu senden.

cmd  /c "mklink link target"

Hier sind die Optionen für 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.

Wenn Sie stattdessen Verknüpfungen über eine GUI erstellen möchten, empfehle ich Link Shell Extension das ist ein Windows Explorer-Plugin zum Erstellen von symbolischen Links, Hardlinks, Junctions und Volume-Mountpoints. Ich benutze es seit Jahren!

Symlinks können lebensrettend sein, wenn sich auf Ihrem Systemlaufwerk C: ein kleineres SSD-Laufwerk befindet und einige aufgeblähte Ordner, die nicht auf SSD-Laufwerken stehen müssen, mit anderen Laufwerken verknüpft werden müssen. Ich benutze das kostenlose WinDirStat , um die Festplattenspeicher zu finden. 

16
Tony O'Hagan

Ich glaube, dass die mit msysGit gelieferte Variable ln einfach versucht, ihre Argumente zu kopieren, anstatt mit Links zu arbeiten. Dies liegt daran, dass Verknüpfungen nur auf NTFS-Dateisystemen funktionieren (Art), und das MSYS-Team wollte ln nicht neu implementieren.

Siehe z. B. http://mingw.5.n7.nabble.com/symbolic-link-to-My-Documents-in-MSYS-td28492.html .

14
Austin Hastings

Für mein Setup ist Git für Windows 2.11.0 unter Windows 8.1 installiert. export MSYS=winsymlinks:nativestrict führt den Trick wie folgt aus: https://github.com/git-for-windows/git/pull/156 Es ist wichtig, die Git Bash Shell als Administrator zu starten, da unter Windows nur Administratoren die symbolischen Links erstellen können. Damit tar -xf funktioniert und die erforderlichen Symlinks erstellt werden können:

  1. Führen Sie Git Bash Shell als Administrator aus
  2. export MSYS=winsymlinks:nativestrict ausführen
  3. Teer laufen lassen
10

Da dies eine der Top-Links ist, die bei der Suche nach dem Erstellen von Symlinks in Msys oder git bash auftauchen, habe ich festgestellt, dass die Antwort darin bestand, set MSYS=winsymlinks:native beim Aufruf von git-cmd.exe (ich führe ConEmu) oder die Kommentarzeile in msys2_Shell.bat

2
swee lim

Erweitern Sie die Antwort von Camilo Martin, wenn Sie die Parameteroption/j für Windows 10 verwenden müssen. Andernfalls gibt der Aufruf nur "Sie verfügen nicht über die erforderlichen Berechtigungen, um diesen Vorgang auszuführen" zurück.

Dies funktioniert für git bash 2.20.1.windows.1/MINGW64 (Windows 10) ohne Administratorrechte (wenn Sie sowohl/old/path als auch/link/path lesen/schreiben können:

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

Ich ziehe Powershell dem CMD vor und dachte, ich würde die Powershell-Version davon teilen.

In meinem Fall besteht es aus Symlinks, die eine ~ /.$-Datei mit einer ~/dotfiles/$ -Datei verknüpfen. Ich habe dies in ein .sh-Skript eingefügt und es mit git-bash ausgeführt:

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