7

NTFS supports all kinds of links including junctions, hard links, soft links, etc. so here's a problem.

Let's say you're recursively deleting a directory which actually contains the above things. It's easy to imagine that your application, whatever that is, instead of deleting all the junctions, soft links which could lead outside of the directory you're interested in, etc. instead traverses them and first deletes all the files within instead.

This could easily lead to a major data loss.

Here's a simple example. You mount a hard disk drive which has another Windows installation.

Let's check the contents of D:\ProgramData:

D:\ProgramData>dir /a
 Volume in drive D has no label.
 Volume Serial Number is 1234-4321

Directory of D:\ProgramData

12/06/2021 12:56 PM <DIR> . 12/06/2021 12:56 PM <DIR> .. 07/14/2009 10:08 AM <JUNCTION> Application Data [C:\ProgramData] 07/14/2009 10:08 AM <JUNCTION> Desktop [C:\Users\Public\Desktop] 07/14/2009 10:08 AM <JUNCTION> Documents [C:\Users\Public\Documents] 07/14/2009 10:08 AM <JUNCTION> Favorites [C:\Users\Public\Favorites] 02/11/2016 03:51 PM <DIR> Microsoft 07/10/2019 03:00 AM <DIR> Microsoft Help 12/23/2019 04:04 PM <DIR> Package Cache 07/14/2009 10:08 AM <JUNCTION> Start Menu [C:\ProgramData\Microsoft\Windows\Start Menu] 07/14/2009 10:08 AM <JUNCTION> Templates [C:\ProgramData\Microsoft\Windows\Templates]

Now what if you try to recursively delete D:\ProgramData? I won't even attempt to do that because I'm afraid C:\ProgramData will be deleted first.

In Linux rm -rf handles this perfectly - it sees symbolic links (to directories) and deletes symbolic links as files, without trying to traverse them.

What's the safe way to recursively delete such directories in Windows?

rmdir /q /s? Something else?

4 Answers4

3

rmdir will delete the symbolic link.

del will delete the links destination but not the link.

rmdir /S /Q will delete the directory recursively and won't follow symlinks.

I have tested and confirmed the behaviour with cmd in Windows 10:

#create directory structure
C:\Users\username\test>mkdir 1 2 3

C:\Users\username\test>mkdir 1\testdir

C:\Users\username\test>mkdir 1\testdir\1

#create symbolic link to directory

C:\Users\username\test>mklink /D testlink 1\testdir\1 symbolische Verknüpfung erstellt für testlink <<===>> 1\testdir\1

C:\Users\username\test>dir

Verzeichnis von C:\Users\username\test

28.12.2021 20:24 <DIR> . 28.12.2021 20:24 <DIR> .. 28.12.2021 20:23 <DIR> 1 28.12.2021 20:23 <DIR> 2 28.12.2021 20:23 <DIR> 3 28.12.2021 20:24 <SYMLINKD> testlink [1\testdir\1] 0 Datei(en), 0 Bytes 6 Verzeichnis(se), 22.185.267.200 Bytes frei

#test rmdir with the named parameters C:\Users\username\test>rmdir /s /q testlink

C:\Users\username\test>dir

Verzeichnis von C:\Users\username\test

28.12.2021 20:25 <DIR> . 28.12.2021 20:25 <DIR> .. 28.12.2021 20:23 <DIR> 1 28.12.2021 20:23 <DIR> 2 28.12.2021 20:23 <DIR> 3 0 Datei(en), 0 Bytes 5 Verzeichnis(se), 22.185.267.200 Bytes frei

C:\Users\username\test>cd 1\testdir\

#obviously the subdirectory in the linked-to directory is still there C:\Users\username\test\1\testdir>dir

Verzeichnis von C:\Users\username\test\1\testdir

28.12.2021 20:23 <DIR> . 28.12.2021 20:23 <DIR> .. 28.12.2021 20:24 <DIR> 1 0 Datei(en), 0 Bytes 3 Verzeichnis(se), 22.184.206.336 Bytes frei

According to this comment rmdir will behave different if invoked from powershell than from cmd, I have however not tested it with powershell.

mashuptwice
  • 3,395
2

For deleting all files which are not a junction, this command should do it:

del /s /a:-l

Where:

  • /s : recurse
  • /a:-l : only files which are not reparse points

NTFS reparse points include Directory junctions, Symbolic links and Volume mount points.

A small test of what will be deleted can be done using the command:

dir /s /a:-l

(I would still take a backup of the folder if it's important.)

harrymc
  • 498,455
1

FastCopy utility does this: http://ipmsg.org/tools/fastcopy.html.en

I am using this program for copying or deleting folders that may contain junctions as subfolders so that the junction targets remain untouched. The junction points are properly copied while copying, even when the target drive is different.

From the program's "Main Settings" you need to go to "Shell Extension" section and enable it. After that you will have Fast Copy-s delete functionality available in the Explorer's right click menu.

Windows Explorer at least in Windows 7 Ultimate works also as wanted while deleting - junction targets remain intact. But copying folders that contain junctions as subfolders in Explorer still does not work as intended - it actually does something that I cannot yet perhaps quite entirely describe: the junction folders seem to be copied as normal folders, but their content is empty.

Roland Pihlakas
  • 159
  • 1
  • 1
  • 8
0

Tried with rmdir /s from command prompt

I created a directory c:\abc1 with a text file in it.

And I created a directory c:\test1 with a subdirectory c:\test1\blah

Within c:\test1\blah I tried creating links to c:\abc1 , a symbolic link or a junction link..

Then when I did rmdir /s on blah, I checked c:\abc1 and it's still there with its contents.

So rmdir /s from cmd prompt, tested in Windows 7, is safe.

C:\>dir c:\abc1
 Volume in drive C has no label.
 Volume Serial Number is 4645-5DCE

Directory of c:\abc1

28/12/2021 19:45 <DIR> . 28/12/2021 19:45 <DIR> .. 28/12/2021 19:45 6 a.txt 1 File(s) 6 bytes 2 Dir(s) 137,425,338,368 bytes free

C:&gt;cd test The system cannot find the path specified.

C:&gt;cd test1

C:\test1>dir Volume in drive C has no label. Volume Serial Number is 4645-5DCE

Directory of C:\test1

28/12/2021 19:45 <DIR> . 28/12/2021 19:45 <DIR> .. 28/12/2021 19:46 <DIR> blah 0 File(s) 0 bytes 3 Dir(s) 137,425,338,368 bytes free

C:\test1>cd blah

C:\test1\blah>dir Volume in drive C has no label. Volume Serial Number is 4645-5DCE

Directory of C:\test1\blah

28/12/2021 19:46 <DIR> . 28/12/2021 19:46 <DIR> .. 0 File(s) 0 bytes 2 Dir(s) 137,425,338,368 bytes free

C:\test1\blah>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.

C:\test1\blah>mklink /d c:\abc1 The syntax of the command is incorrect. 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.

C:\test1\blah>mklink /d qq c:\abc1 symbolic link created for qq <<===>> c:\abc1

C:\test1\blah>dir Volume in drive C has no label. Volume Serial Number is 4645-5DCE

Directory of C:\test1\blah

28/12/2021 19:47 <DIR> . 28/12/2021 19:47 <DIR> .. 28/12/2021 19:47 <SYMLINKD> qq [c:\abc1] 0 File(s) 0 bytes 3 Dir(s) 137,425,469,440 bytes free

C:\test1\blah>dir qq Volume in drive C has no label. Volume Serial Number is 4645-5DCE

Directory of C:\test1\blah\qq

28/12/2021 19:45 <DIR> . 28/12/2021 19:45 <DIR> .. 28/12/2021 19:45 6 a.txt 1 File(s) 6 bytes 2 Dir(s) 137,425,469,440 bytes free

C:\test1\blah>cd ..

C:\test1>rmdir /s blah blah, Are you sure (Y/N)? y

C:\test1>dir c:\abc1 Volume in drive C has no label. Volume Serial Number is 4645-5DCE

Directory of c:\abc1

28/12/2021 19:45 <DIR> . 28/12/2021 19:45 <DIR> .. 28/12/2021 19:45 6 a.txt 1 File(s) 6 bytes 2 Dir(s) 137,425,379,328 bytes free

C:\test1>cd blah The system cannot find the path specified.

C:\test1>md blah

C:\test1>dir Volume in drive C has no label. Volume Serial Number is 4645-5DCE

Directory of C:\test1

28/12/2021 19:47 <DIR> . 28/12/2021 19:47 <DIR> .. 28/12/2021 19:47 <DIR> blah 0 File(s) 0 bytes 3 Dir(s) 137,424,666,624 bytes free

C:\test1>cd blah

C:\test1\blah>dir Volume in drive C has no label. Volume Serial Number is 4645-5DCE

Directory of C:\test1\blah

28/12/2021 19:47 <DIR> . 28/12/2021 19:47 <DIR> .. 0 File(s) 0 bytes 2 Dir(s) 137,424,666,624 bytes free

C:\test1\blah>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.

C:\test1\blah>mklink /J ww c:\abc1 Junction created for ww <<===>> c:\abc1

C:\test1\blah>dir Volume in drive C has no label. Volume Serial Number is 4645-5DCE

Directory of C:\test1\blah

28/12/2021 19:48 <DIR> . 28/12/2021 19:48 <DIR> .. 28/12/2021 19:48 <JUNCTION> ww [c:\abc1] 0 File(s) 0 bytes 3 Dir(s) 137,424,715,776 bytes free

C:\test1\blah>dir ww Volume in drive C has no label. Volume Serial Number is 4645-5DCE

Directory of C:\test1\blah\ww

28/12/2021 19:45 <DIR> . 28/12/2021 19:45 <DIR> .. 28/12/2021 19:45 6 a.txt 1 File(s) 6 bytes 2 Dir(s) 137,424,715,776 bytes free

C:\test1\blah>cd ..

C:\test1>rmdir /s blah blah, Are you sure (Y/N)? y

C:\test1>dir c:\abc1 Volume in drive C has no label. Volume Serial Number is 4645-5DCE

Directory of c:\abc1

28/12/2021 19:45 <DIR> . 28/12/2021 19:45 <DIR> .. 28/12/2021 19:45 6 a.txt 1 File(s) 6 bytes 2 Dir(s) 137,424,740,352 bytes free

C:\test1>

Really you should be able to do the test yourself very easily.

One comment mentions that powershell rmdir is different.. I can't comment much re powershell, I don't use it that much. I see that powershell's rmdir does give different output e.g. rmdir says "cmdlet Remove-Item at command pipeline..." so seems to be very different to the cmd one, i'm not familiar with it.

barlop
  • 25,198