Reputation: 14685
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!
Upvotes: 17
Views: 24254
Reputation: 81
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.) ) )
Upvotes: 2
Reputation: 2114
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
)
Upvotes: 7
Reputation: 2054
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!
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
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!
Upvotes: 23
Reputation: 3081
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. )
Upvotes: 1
Reputation: 3081
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.
Upvotes: 2
Reputation: 31
This also works:
dir /al|find /i "java"|find /i "junction" && ( echo directory is a symlink )
Upvotes: 3
Reputation: 71
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
Upvotes: 4
Reputation: 37569
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
Upvotes: 12