Git Bash Shell не создает символические ссылки

Когда я пытаюсь создать символическую ссылку из оболочки Git Bash, она терпит неудачу каждый раз все время:

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

Единственное, что он делает, помимо сообщения об ошибке, - создать пустой каталог с именем (в данном случае) testlink.

Я не вижу никаких проблем с исполняемым файлом ln. Например, он принадлежит мне и помечен как исполняемый файл:

$ which ln
/bin/ln

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

У меня также есть текущий каталог (~, который /c/Users/bzisad0):

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

У меня есть права администратора, и я попытался открыть оболочку Git Bash с "Запуск от имени администратора", но это не имеет никакого значения.

Я попытался открыть свойства Windows для ln.exe и установить уровень привилегий для "Запускать эту программу как администратор", но это не помогает.

Я перешел в свойства Security → Advanced в Windows и сделал себя (а не группу "Администраторы" ) владельцем, но это ничего не исправить.

Я в недоумении. Я не знаю, в конечном итоге это сообщение об ошибке происходит от ln, от Bash или от Windows, или от того, как мне может не хватать разрешения. Как я могу понять это?

Ответ 1

Возможно, хотя и крайне неудобно создавать символическую ссылку в MSYSGIT.

Во-первых, нам нужно убедиться, что мы в Windows. Вот пример функции для проверки того, что:

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

Теперь мы не можем сделать cmd /C, потому что MSYSGIT будет лелеять этот аргумент и превратить его в C:. Кроме того, не стоит искушать использование /K, он работает только в том случае, если у вас нет диска K:.

Поэтому, пока он заменит это значение на аргументах программы, он не будет использоваться для heredocs. Мы можем использовать это в наших интересах:

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

Также: обратите внимание, что я включил /D, потому что меня интересуют только символические ссылки каталога; Windows имеет это различие. С большим трудом вы можете написать функцию ln() { ... }, которая обертывает Windows API и служит полным решением для вставки, но это... оставлено как упражнение для читателя.


Изменить: Как благодарность за принятый ответ, здесь более полная функция.

# 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 a directory or not. Infer that.
            # Also: note that we convert `/` to `\`. In this case it 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 parameters are backwards.
            ln -s "$2" "$1"
        fi
    fi
}

Также обратите внимание на несколько вещей:

  • Я только что написал это и вкратце протестировал его на Win7 и Ubuntu, попробуйте сначала, если вы с 2015 года и используете Windows 9.
  • NTFS имеет точки повторной обработки и точки соединения. Я выбрал точки повторной обработки, потому что это больше фактическая символическая ссылка и работает для файлов или каталогов, но точки соединения будут полезны для использования в XP, кроме как для каталогов.
  • Некоторые файловые системы, в частности, FAT, не поддерживают символические ссылки. Современные версии Windows больше не поддерживают загрузку, но Windows и Linux могут их монтировать.

Бонусная функция: удалите ссылку.

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

Ответ 2

Обходной путь - запустить mklink из Bash. Это также позволяет вам создать символическую ссылку или соединение.

Позаботьтесь о том, чтобы отправить команду mklink в качестве единственного аргумента cmd...

cmd  /c "mklink link target"

Вот варианты для 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.

Если вы хотите вместо этого создавать ссылки с помощью графического интерфейса... Я рекомендую Link Shell Extension, которая является плагином Windows Explorer для создания символических ссылок, жестких ссылок, переходов и точек монтирования тома. Я использую это в течение многих лет!

Симлинки могут быть спасением жизни, если на вашем системном диске C: есть SSD-диск меньшего размера, и вам нужно символически связать некоторые раздутые папки, которые не должны быть на SSD, с другими дисками. Я использую бесплатный WinDirStat, чтобы найти место на диске.

Ответ 3

Я считаю, что ln, который поставляется с msysGit, просто пытается скопировать его аргументы, а не скриптировать ссылки. Это связано с тем, что ссылки работают (только) на файловых системах NTFS, а команда MSYS не хочет переопределять ln.

См., например, http://mingw.5.n7.nabble.com/symbolic-link-to-My-Documents-in-MSYS-td28492.html

Ответ 4

Для моей установки это Git для Windows 2.11.0, установленный в Windows 8.1 export MSYS=winsymlinks:nativestrict делает то, что описано здесь: https://github.com/git-for-windows/git/pull/156 Это важно запускать оболочку Git Bash от имени администратора, поскольку в Windows только администраторы могут создавать символические ссылки. Итак, чтобы заставить tar -xf работать и создать необходимые символические ссылки:

  1. Запустите Git Bash shell от имени администратора
  2. Запустите export MSYS=winsymlinks:nativestrict
  3. Запустить смолу

Ответ 5

Так как это одна из верхних ссылок, которые возникают при поиске символических ссылок в Msys или git bash, я нашел ответ на добавление set MSYS=winsymlinks:native при вызове git-cmd.exe (я запускаю ConEmu) или раскомментирую ту же строку в msys2_shell.bat

Ответ 6

Я предпочитаю Powershell CMD и решил поделиться версией PowerShell.

В моем случае это состоит из создания символических ссылок, связывающих файл ~/.$ с ~/dotfiles/$ file, для конфигурации dotfile. Я поместил это в сценарий .sh и запустил его с помощью git-bash:

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

Ответ 7

Расширение Camilo Martin anwser, так как вам нужно использовать параметр параметра /j для Windows 10; в противном случае вызов просто вернет "У вас недостаточно прав для выполнения этой операции".

Это работает для git bash 2.20.1.windows.1/MINGW64 (Windows 10) без прав администратора (если вы можете читать/писать как /old/path, так и /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