14

I learned just now that this is a way to test in a batch file if a file is a link:

dir %filename% |  find "<SYMLINK>" && (
   do stuff
)

How can I do a similar trick for testing if a directory is a symlink. It doesn't work to just replace <SYMLINK> with <SYMLINKD>, because dir %directoryname% lists the contents of the directory, not the directory itself.

It seems like I need some way to ask dir to tell me about the directory in the way that it would if I asked in the parent directory. (Like ls -d does in unix).

Or any other way of testing if a directory is a symlink?

Thanks!

GreenAsJade
  • 14,459
  • 11
  • 63
  • 98

8 Answers8

21

You have three methods

Solution 1: fsutil reparsepoint

Use symlink/junction with fsutil reparsepoint query and check %errorlevel% for success, like this:

set tmpfile=%TEMP%\%RANDOM%.tmp

fsutil reparsepoint query "%DIR%" >"%tmpfile%"
if %errorlevel% == 0 echo This is a symlink/junction
if %errorlevel% == 1 echo This is a directory

This works, because fsutil reparsepoint query can't do anything on a standard directory and throws an error. But the permission error causes %errorlevel%=1 too!

Solution 2: dir + find

List links of the parent directory with dir, filter the output with find and check %errorlevel% for success, like this:

set tmpfile=%TEMP%\%RANDOM%.tmp

dir /AL /B "%PARENT_DIR%" | find "%NAME%" >"%tmpfile%"
if %errorlevel% == 0 echo This is a symlink/junction
if %errorlevel% == 1 echo This is a directory

Solution 3: for (the best)

Get attributes of the directory with for and check the last from it, because this indicates links. I think this is smarter and the best solution.

for %i in ("%DIR%") do set attribs=%~ai
if "%attribs:~-1%" == "l" echo This is a symlink/junction

FYI: This solution is not dependent on %errorlevel%, so you can check "valid errors" too!

Sources

aschultz
  • 1,658
  • 3
  • 20
  • 30
andras.tim
  • 1,964
  • 1
  • 13
  • 23
  • Regarding solution 3: it's actually not the last, but the 9th character - `%attribs:~8,1%`. Eleven characters are returned in total on Windows 8.1. – CodeManX Aug 20 '15 at 12:30
  • For solution 1, to not run into the *invalid error* problem, verify with `findstr` as such: `fsutil reparsepoint query scripts 2>&1 | findstr /r "^Tag\ Value:\ Symbolic\ Link$" > /nul` – setempler Apr 12 '19 at 10:03
  • 1
    @setempler, I think triggering on the exit code is much stable thing, then parse the human-readable output. In other hands, you can redirect the STDERR to `/nul` w/ my solution also. – andras.tim Apr 13 '19 at 11:58
  • solution 3's IF statement with @CodeManX 's addition fails, as if the comparand is not expanded. – Unknow0059 Mar 04 '23 at 06:00
12

general code:

fsutil reparsepoint query "folder name" | find "Symbolic Link" >nul && echo symbolic link found || echo No symbolic link

figure out, if the current folder is a symlink:

fsutil reparsepoint query "." | find "Symbolic Link" >nul && echo symbolic link found || echo No symbolic link

figure out, if the parent folder is a symlink:

fsutil reparsepoint query ".." | find "Symbolic Link" >nul && echo symbolic link found || echo No symbolic link
Endoro
  • 37,015
  • 8
  • 50
  • 63
  • Sweet, thanks - it was really helpful to have the general and some specific examples, and I just found out that there is fsutil ... some more learning to do! – GreenAsJade Sep 19 '13 at 05:10
  • 5
    This will only work with English-language Windows. For some reason MS loves to localize command-line strings... The fix is just don't use `find` (no need to, the errorlevel is enough). – Camilo Martin Aug 20 '14 at 15:58
  • I always make my answers here for a specific question by a specific user. A batch file/cmd line is never the solution for all _similar_ questions. Moreover, this is not a Windows specific issue, you can localise Linux as well. – Endoro Aug 20 '14 at 23:37
  • Nice... how to detect if one of the folders in path is a SymLink... not only the immediate parent... but any ancestor folder ??? – ZEE Apr 11 '17 at 19:40
6

Update: this solved my problem, but as commenters noted, dir will show both directory symlinks and directory junctions. So it's wrong answer if junctions are there.


Simple dir /A:ld works fine

dir /?:

DIR [drive:][path][filename] [/A[[:]attributes]] …

/A          Displays files with specified attributes.  
attributes   D  Directories                R  Read-only files  
             H  Hidden files               A  Files ready for archiving  
             S  System files               I  Not content indexed files  
             L  Reparse Points             -  Prefix meaning not  

Note that to execute a command only for non-link folders, you can use the attribute negation form:

for /F "usebackq" %%D in (`dir /A:D-L /B some-folder`) do (
    some-command some-folder\%%D
)
Lawrence Dol
  • 63,018
  • 25
  • 139
  • 189
zxcat
  • 2,054
  • 3
  • 26
  • 40
  • 1
    Not that as it stands this isn't an answer to the question, because it doesn't _test_ whether a directory is a symlink, it simply lists those that are. To answer the question, you'd need to elaborate on how to test the result. Out of interest, what is a "reparse point"? – GreenAsJade Nov 16 '16 at 21:54
  • A _reparse point_ is any file symlink, or directory symlink, or directory junction: all of which will (if present) be listed by the DIR A:L command. – Ed999 Jan 20 '17 at 20:14
  • @Ed999, ok, I see, thanks. I used this without junctions, so it worked fine – zxcat Feb 25 '17 at 20:16
4

Actually, DIR works fine if you append an asterisk to the filename, thus:

dir %filename%* |  find "<SYMLINKD>" && (
   do stuff
)

GreenAsJade called my attention to this solution's failure when there is another entry in the directory that matches %filename%*. I believe the following wiull work in all cases:

set MYPATH=D:\testdir1
set FILENAME=mylink
set FULL=%MYPATH%\%FILENAME%
set SP1=0
for /f "tokens=4,5 delims= " %%A IN ('dir /L /N %FULL%*') do (
    if %%B EQU %FILENAME% (
    if "%%A" EQU "<SYMLINKD>" set SP1=1
    )
)
if %sp1% EQU 0 echo It's not there.
if %sp1% EQU 1 echo BINGO!
Pause
Frank
  • 71
  • 1
  • 4
  • What if there are other files in the directory that match %filename%*? – GreenAsJade Oct 30 '14 at 00:13
  • It would still work if there were such files because they would not return "". It would fail if there was another directory symbolic link that matched %filename%*. – Frank Oct 30 '14 at 00:22
  • You have done me a favor by bringing this up because the file I am writing would fail due to this problem, and I had not thought about it. As far as I can tell, the following works in all cases: set MYPATH=D:\testdir1 set FILENAME=mylink set FULL=%MYPATH%\%FILENAME% set SP1=0 for /f "tokens=4,5 delims= " %%A IN ('dir /L /N %FULL%*') do ( if %%B EQU %FILENAME% ( if "%%A" EQU "" set SP1=1 ) ) if %sp1% EQU 0 echo It's not there. if %sp1% EQU 1 echo BINGO! Pause – Frank Oct 30 '14 at 02:16
  • Sorry about the terrible formatting. The five-minute window for editing timed out before I got it figured out. – Frank Oct 30 '14 at 02:24
  • Maybe put that new info in the actual answer :) – GreenAsJade Oct 30 '14 at 03:58
  • What if `` is part of a non-symlink filename? This will also fail. – ulidtko Dec 10 '14 at 13:55
  • cannot be part of a file or folder name because "<" and ">" are not legal in file and folder names. – Frank Jan 08 '15 at 03:23
  • Surely a more practical approach is to specify a directory and search its entire contents, listing all symbolic links or junctions that are present in it - see my proposed batch file solution elsewhere on this page. You are then searching potentially dozens of files at once. There would also, then, be no possibility of conflicting duplicate filenames, since the NTFS file system excludes that possibility. – Ed999 Jan 20 '17 at 20:36
3

This also works:

dir /al|find /i "java"|find /i "junction" && ( echo directory is a symlink )

Hames
  • 31
  • 1
1

The appropriate DIR command is shown in the following batch file (reparse.bat) -

  ::  Specify the Directory to search
  SET directory=C:\Users\%username%\Desktop\TEST1

  ::  Results Text
  echo SEARCH OF DIRECTORY FOR REPARSE POINTS & echo.

  ::  List files with ATTRIBUTE L (Reparse Points)
  DIR "%directory%" /A:L

  echo. && echo  Notes - && echo.
  echo  There are 3 types of Reparse points: && echo.
  echo  ^<JUNCTION^> is a Directory Junction
  echo  ^<SYMLINKD^> is a Directory SymLink
  echo  ^<SYMLINK^>  is a File SymLink
  echo. && echo.
Ed999
  • 2,801
  • 2
  • 16
  • 19
1

An alternative approach is to treat each of the three types of reparse point separately, in the following batch file (reparse2.bat), which can be easily modified to search only for the type of link you are interested in -

  ::  Directory to Search
  SET directory=C:\Users\%username%\Desktop\TEST1

  ::  Results Text
  echo SEARCH OF DIRECTORY: %directory% & echo.

  ::  Find FILE SymLinks in directory
  dir "%directory%" | find "<SYMLINK>" && (
    echo This is a SymLink FILE
  ) && ( echo. )

  ::  Find DIRECTORY SymLinks in directory
  dir "%directory%" | find "<SYMLINKD>" && (
    echo This is a SymLink DIRECTORY
  ) && ( echo. )

  ::  Find JUNCTIONS in directory
  dir "%directory%" | find "<JUNCTION>" && (
    echo This is a Directory JUNCTION
  ) && ( echo. ) && ( echo. )
Ed999
  • 2,801
  • 2
  • 16
  • 19
1

A simple example script for Windows 10.

Info: If it exist as SymLink in %localappdata%\MegaDownloader folder, execute MegaDownloader.exe. If it doesn't exist as a SymLink in %localappdata%\MegaDownloader, use mklink to create SymLink PortableData path of current folder to %localappdata%\MegaDownloader, then runs MegaDownloader.exe.

fsutil reparsepoint query "%localappdata%\MegaDownloader" | find "Substitute" >nul && GOTO MD || mklink /D /J "%localappdata%\MegaDownloader" "%cd%\PortableData" >nul 2>&1
    
:MD
"%~dp0\MegaDownloader.exe"

OR

For symbolic and/or directory check, this commands is more robust:

set CheckFolder=D:\ExampleFolder

FOR /f "delims=<> tokens=2" %g in ('dir %CheckFolder%* ^| find "<"') do ( IF %g==DIR (echo %CheckFolder% is real a directory.) ELSE (IF %g==JUNCTION (echo %CheckFolder% is a SymbolicLink/Junction.) ) )

FOR /F "tokens=3*" %s IN ('fsutil reparsepoint query "%CheckFolder%" ^| findstr /ic:"Print Name:"') do SET "SymLinkDir=%s"

(IF NOT EXIST "%SymLinkDir%" (echo But the junction's target directory ^("%SymLinkDir%"^) is not existed!) ELSE ( IF EXIST "%SymLinkDir%" (echo And the junction's target directory ^("%SymLinkDir%"^) is existed.) ) )

pureocean
  • 61
  • 3