Как перейти по символической / мягкой ссылке в cmd или PowerShell?
Мой поиск только показал мне, как создавать символические ссылки, используя mklink в cmd. Я видел некоторые вещи, говорящие об использовании readlink, но PowerShell и cmd не знают, что такое readlink, и cd, очевидно, не работает. Итак, как мне следовать одному?
3 ответа
На ваш вопрос я сделал этот командный файл:
mkdir truedir
dir > truedir\fileone.txt
mklink /d symdir truedir
cd symdir
dir
И я не нашел никаких проблем, чтобы получить содержимое символьной ссылки на каталог из командной строки. Нет проблем также с powershell 5.1 (win 10):
Get-ChildItem C:\Users\ssacc\OneDrive\Desktop\test2\symdir
Можете ли вы дать нам пример кода (пакет или PowerShell - то же самое), чтобы повторить вашу проблему?
Чтобы избежать путаницы, связанной с вашим вопросом:
Файлы ярлыков Windows (
*.lnk
файлы), которые являются функцией оболочки Windows (GUI), отличаются от символических ссылок (символических ссылок), которые являются функцией файловой системы (NTFS).Файлы ярлыков - которые вас интересуют - хранят путь к файлу или папке, на которые они указывают, внутри файла, поэтому:
- Вы не можете напрямую
cd
в папку назначения ярлыка файла, потому что команды файловой системы, такие какcd
ничего не знаю о содержимом файлов. - Вы должны прочитать содержимое файла ярлыка, чтобы определить его цель, которую затем можно передать
cd
или жеSet-Location
(в PowerShell). Формат файла ярлыка - это двоичный файл, который можно прочитать через встроенный COM-компонент, который предоставляет функциональность оболочки Windows; например, чтобы определить целевую папку файла ярлыка с именем
Samples.lnk
и перейдите в эту папку, используйте PowerShell:# NOTE: * Despite the name "CreateShortcut()", the method is also # used to *read* shortcut files. # * Prefixing the filename with "$PWD/" is needed in order # to target a file in the current directory, because # the method doesn't know what PowerShell's current dir. is. cd (New-Object -ComObject WScript.Shell).CreateShortcut("$PWD/Samples.lnk").TargetPath
- Вы не можете напрямую
Симлинки, напротив:
(обычно) прозрачно перенаправить к своей цели, то есть к элементу файловой системы (файлу или папке), на который они указывают.
Поэтому вы можете использовать
cd
непосредственно с символической ссылкой на папку, но обратите внимание, что это все еще путь симлинка, который показан.Чтобы напечатать цель символической ссылки - сродни тому, что
readlink
утилита работает на Unix-подобных платформах - используйте PowerShell; например, чтобы напечатать цель символической ссылки с именемSamples
в текущем каталоге:(Get-Item Samples).Target # Or, after running `cd Samples`: (Get-Item .).Target
Обратите внимание, что не просто получить цель символической ссылки в
cmd.exe
, но если вы используетеdir /al <link-path>*
в списке также будет показан целевой путь ссылки после имени, заключенного в[...]
; обратите внимание, что трейлинг*
необходим для отображения информации о самой ссылке, а не о ее цели; обратите внимание, что, хотя и маловероятно, это может соответствовать другим ссылкам, которые также начинаются с того же пути.
В отличие от файлов ярлыков, символические ссылки все еще редки в мире Windows, не в последнюю очередь потому, что до Windows 10 они неизменно требовали прав администратора; в Windows 10, если включен режим разработчика (администратором), даже пользователи без прав администратора / процессы без повышенных прав теперь могут создавать символические ссылки - см. https://blogs.windows.com/buildingapps/2016/12/02/symlinks-windows-10/, которая также объясняет, почему символические ссылки, вероятно, будут расширяться в будущем.
Хорошо, я только что опубликовал этот ответ в другом подобном вопросе, поэтому решил опубликовать его и здесь. Я бы хотел, чтобы этот вопрос появился в поиске, как и другой вопрос, потому что ответ @mklement0 великолепен. Но вот мое решение, которое может переходить по вложенным ссылкам на истинный файл или каталог в PowerShell (я искал решение для PS, а не CMD).
На данный момент подход с двойным cd является самым надежным/универсальным, который я могу найти для обработки ситуации смешанных относительных/абсолютных путей в именах файлов и целевых объектах, и я протестировал несколько сценариев.
function getLinkTarget($fn) {
$op=$PWD #Save original path
while($t=(Get-Item $fn).Target) { #Get link target
cd (Split-Path -Parent $fn) #cd to parent of file/dir
cd (Split-Path -Parent $t) #cd again to parent of target
$fn=(Split-Path -Leaf $t) #Set filename to relative target
}
$fn=(Join-Path $PWD $fn) #Make path absolute
cd $op #Change back to original path
return $fn
}