删除perl脚本中的Windows符号链接



假设我创建了一些Windows符号链接,如:

rd /s /q source withlink linkdir
mkdir source
mkdir withlink
echo blah > source/myfile
cd withlink
touch blah
mklink mylink ..sourcemyfile
@REM mklink /d linkdir ..source
cd ..

我可以用删除外壳中包含符号链接的目录

rd /s /q withlink

我在perl脚本中有同样的任务要做,我们目前使用的是cygwin"rm-rf"。不幸的是,我们使用的是cygwin 1.5,rm和rm-rf在我想要使用的符号链接上不能正常工作(它们删除符号链接内容而不是符号链接)。

如果我尝试:

use File::Path qw( rmtree ) ;
rmtree( ['withlink'] ) ;

如果我没有任何目录符号链接(比如上面创建链接序列中的REM'e),那么perl的rmtree最终会表现得像cygwin,我最终会删除原始目录的目录内容。

有人建议我使用另一种perl递归目录删除方法吗。我只想到了一个shell调用:

system("rd /s /q withlink") ;

但这需要我测试平台,并为Windows和Unix提供不同的perl代码。

编辑:请注意,与Unix不同,unlink()不能删除目录符号链接,至少在perlv5.6.0中是这样,这是我们的构建系统目前正在使用的。但是,rmdir()确实可以删除windows目录符号链接。

您必须使用rmdir来删除Windows中的目录符号链接和连接点,并且必须仅使用unlink来删除文件的符号链接。原因是目录符号链接和连接点实际上是一个带有额外文件系统元数据(称为重分析点数据)的空目录。类似地,到文件的符号链接是带有重分析点数据的空文件。当您阅读Microsoft NTFS文档时,这样的目录或文件被称为重分析点。重分析点类型由所谓的重分析点TAG确定。用户可以看到两个重分析点的标签作为"链接":

  1. IO_REPARSE_TAG_SYMLINK-如果设置在目录上,则是指向目录的符号链接;如果设置在文件上,则为指向文件的符号链接
  2. IO_REPARSE_TAG_MOUNT_POINT-只能在目录上设置-它被称为"连接点"。它可以是到另一个目录的"链接",但也可以是整个设备(卷)的"装入点"

总结:

  1. 删除指向目录和连接点的符号链接,就好像它们是目录一样(事实上,如果检查这样一个东西的属性,它有两个:FILE_ATTRIBUTE_DIRECTORY和FILE_ATTRIBUTE_REPARSE_POINT)
  2. 您删除文件的符号链接,就好像它们是文件一样
  3. 在上述两种情况下,仅删除链接/连接(而不是目标)
  4. 要查明文件/文件夹是否是链接(所有类型):如果您调用GetFileAttributesGetFileInformationByHandleFindNextFile,则属性包含FILE_ATTRIBUTE_REPARSE_POINT标志(例如:WIN32_FIND_DATA::dwFileAttributes)。如果它是指向目录的链接,它还包含标志FILE_ATTRIBUTE_DIRECTORY(请参见1。

希望能有所帮助。

最新更新