Native alternative for readlink on Windows
Asked Answered
P

2

12

Windows native alternative for ln -s is mklink.

Is there any native alternative for readlink? Or how to natively identify if the file is symlink?

Phonogram answered 8/11, 2012 at 21:49 Comment(0)
B
6

I don't believe there's any tool directly equivalent to readlink. But you can see in the output of dir whether an item is a symlink or not, so you can still determine this from the command line or in a script.

Test whether it's a symlink or not

You can pretty easily test whether a given file is a symlink using syntax like:

 dir mysymlink  | find "<SYMLINK>" >NUL
 if not errorlevel 1  echo. It's a symlink!

Errorlevel will be 0 in the case that "<SYMLINK>" is found, and will be 1 otherwise.

Determine the target of a symlink

Determining the actual target of the symlink is another matter, and in my opinion not as straight-forward. The output of dir mysymlink | find "<SYMLINK>" might look like

11/13/2012  12:53 AM    <SYMLINK>      mysymlink [C:\Windows\Temp\somefile.txt]

You can parse this, but some of the characters make it difficult to deal with all in one variable, so I found it easier to deal with a temporary file:

 dir mysymlink | find "<SYMLINK>" > temp.txt
 for /f "tokens=6" %i in (temp.txt) do @echo %i

This yields output like [C:\Windows\Temp\somefile.txt]. (Remember to use %%i within any batch scripts; the above is from the command prompt.)

To get the result without the brackets, you can do something like:

 dir mysymlink | find "<SYMLINK>" > temp.txt
 for /f "tokens=6" %i in (temp.txt) do set answer=%i
 echo %answer:~1,-1%

The variable %answer% contains the result with the brackets, so %answer:~1,-1% is the result without the first or the last character.

Burse answered 13/11, 2012 at 9:13 Comment(5)
Thank you for exhausting response. Ok, we have solution for files, and what about directories, what more non empty directories with symlinks in it?Gwenny
You can apply some of the above techniques to symlink directories. They are identified by <SYMLINKD>, but note that dir mysymlinkdir will display the contents of that symlink dir rather than the summary info. So perhaps dir |find "mysymlinkdir" |find "<SYMLINKD>" would be a useful construct.Burse
dir is not recognized as command on Windows 7 - at least not on my machine.Displume
@Displume dir is an internal command to cmd.exe and not an executable file.Sophy
@LarsRohrbach DIR | find ... could return 2 lines if two symlink dirs eg. mysymlinkdir and mysymlinkdir2 existed, so you need to check dir name matched if you used that. (Same issue in my comment on the other answer below). Resurrected this question as I am coding a similar script to change directories to the target dir of a symbolic dir link.Scabious
J
9

No need to redirect the stdout to a temp.txt file. You can simply do this in one line:

for /f "tokens=6" %i in ('dir mysymlink ^| FIND "<SYMLINK>"') do @echo %i

Also note that the above method by Lars only applies to "file" symlinks. That method has to be adjusted for directory symlinks since passing a directory to the "dir" command will list out that directories actual contents (which won't have itself in there)

So you would use:

for /f "tokens=6" %i in ('dir mysymlink* ^| FIND "<SYMLINKD>"') do @echo %i

Note the inclusion of the * in the dir call and the addition of the "D" in the FIND

The asterisk will prevent dir from listing the contents of that directory.

To further simplify the process to work for either file or directory symlinks, you would simply always include the asterisk and for the FIND argument you would change it to a partial match so that it matches with or without "D" on the end

for /f "tokens=6" %i in ('dir mysymlink* ^| FIND "<SYMLINK"') do @echo %i

And finally, since that method actually returns the file inside the brackets [].. you would be better off delimiting those, leaving you with the final method:

for /f "tokens=2 delims=[]" %i in ('dir mysymlink* ^| FIND "<SYMLINK"') do @echo %i
Jeromyjerreed answered 10/12, 2014 at 17:39 Comment(1)
The code does not work universally. Consider C:\app\ and C:\app2\ are both symbolic directory links and you want the target for C:\app. Your code must check token 5. Re-parse "app [target-path-string]" and only return that as the answer.Scabious
B
6

I don't believe there's any tool directly equivalent to readlink. But you can see in the output of dir whether an item is a symlink or not, so you can still determine this from the command line or in a script.

Test whether it's a symlink or not

You can pretty easily test whether a given file is a symlink using syntax like:

 dir mysymlink  | find "<SYMLINK>" >NUL
 if not errorlevel 1  echo. It's a symlink!

Errorlevel will be 0 in the case that "<SYMLINK>" is found, and will be 1 otherwise.

Determine the target of a symlink

Determining the actual target of the symlink is another matter, and in my opinion not as straight-forward. The output of dir mysymlink | find "<SYMLINK>" might look like

11/13/2012  12:53 AM    <SYMLINK>      mysymlink [C:\Windows\Temp\somefile.txt]

You can parse this, but some of the characters make it difficult to deal with all in one variable, so I found it easier to deal with a temporary file:

 dir mysymlink | find "<SYMLINK>" > temp.txt
 for /f "tokens=6" %i in (temp.txt) do @echo %i

This yields output like [C:\Windows\Temp\somefile.txt]. (Remember to use %%i within any batch scripts; the above is from the command prompt.)

To get the result without the brackets, you can do something like:

 dir mysymlink | find "<SYMLINK>" > temp.txt
 for /f "tokens=6" %i in (temp.txt) do set answer=%i
 echo %answer:~1,-1%

The variable %answer% contains the result with the brackets, so %answer:~1,-1% is the result without the first or the last character.

Burse answered 13/11, 2012 at 9:13 Comment(5)
Thank you for exhausting response. Ok, we have solution for files, and what about directories, what more non empty directories with symlinks in it?Gwenny
You can apply some of the above techniques to symlink directories. They are identified by <SYMLINKD>, but note that dir mysymlinkdir will display the contents of that symlink dir rather than the summary info. So perhaps dir |find "mysymlinkdir" |find "<SYMLINKD>" would be a useful construct.Burse
dir is not recognized as command on Windows 7 - at least not on my machine.Displume
@Displume dir is an internal command to cmd.exe and not an executable file.Sophy
@LarsRohrbach DIR | find ... could return 2 lines if two symlink dirs eg. mysymlinkdir and mysymlinkdir2 existed, so you need to check dir name matched if you used that. (Same issue in my comment on the other answer below). Resurrected this question as I am coding a similar script to change directories to the target dir of a symbolic dir link.Scabious

© 2022 - 2024 — McMap. All rights reserved.