在 Windows 上列出非符号 link

Listing non symbolic link on Windows

我正在尝试列出特定目录中的非符号 link,然后将其删除。

非符号 links 定义:除了使用命令 MKLINK /H

创建的文件之外的任何文件

为了识别那些非符号 link,我使用了以下方法:

#> fsutil hardlink list %file% | find /c /v ""

当指定的 %file% 是符号时 link 它 return 是一个大于 1 的数字,当它只是一个简单的文件时,它 return 是 1. 到目前为止太好了!

当我需要自动执行此过程并获取这样的 return 来比较它是否大于 1

时,我的问题就开始了

这就是我要获取的代码 运行 属性:

@echo off    
set some_dir=C:\TEMP\    
for /f %%a in ('dir /b %some_dir%') do (
    set count=fsutil hardlink list %%a | find /c /v ""
    if %count% -EQU 1 del /Q %%a        
)

有人能解释一下如何对 %count% 变量进行这种归因和比较吗?

您的代码中存在一些问题:

  • 您需要 delayed expansion 因为您正在设置(写入) 扩展(读取)同一带括号的代码块中的变量 count(即for /F %%a 循环);
  • 在你的 for /F %%a 循环中你需要声明选项 "eol=| delims=" 以免 运行 遇到名称以 ; 开头的文件的麻烦(这样会被忽略由于默认的 eol=; 选项)和名称中有 white-space 的那些(由于默认的 [=18,您只会收到第一个 white-space 之前的位置=] SPACETAB 以及默认选项 tokens=1(有关详细信息,请参阅 for /?) ;
  • dir /B returns 仅文件名,因此 %%a 实际上指向当前目录中的文件而不是 C:\TEMP\;要解决这个问题,只需先通过 cd;
  • 切换到该目录
  • 要捕获命令(行)的输出并将其分配给变量,请使用另一个 for /F 循环和 set;这个循环只会迭代一次,因为 find /C returns 只有一行;注意下面的转义管道^|,要求不要马上执行;
  • 没有比较运算符-EQU,需要去掉-来判断是否相等;
  • 使用引用的 set 语法是个好主意,因为它对有毒字符最有效;
  • 文件和目录路径通常应该用引号引起来,因为它们可能包含标记定界符或其他有毒字符;

固定脚本如下:

@echo off
setlocal EnableDelayedExpansion
pushd "C:\TEMP\" || exit /B 1
for /F "eol=| delims=" %%a in ('dir /B "."') do (
    for /F %%b in ('
        fsutil hardlink list "%%a" ^| find /C /V ""
    ') do (
        set "count=%%b"
    )
    if !count! EQU 1 del "%%a"
)
popd
endlocal

这甚至可以简化:

@echo off
pushd "C:\TEMP\" || exit /B 1
for /F "eol=| delims=" %%a in ('dir /B "."') do (
    for /F %%b in ('
        fsutil hardlink list "%%a" ^| find /C /V ""
    ') do (
        if %%b EQU 1 del "%%a"
    )
)
popd

由于内部 for /F 循环总是只迭代一次,我们可以将 if 查询移到里面,从而避免定义一个辅助变量,这是我们唯一需要延迟扩展的变量。

我正在尝试列出特定目录中的非符号链接,然后将其删除。

您的代码存在一些问题。

for /f %%a in ('dir /b %some_dir%') do (

dir /b 不起作用,因为它没有 return 具有完整路径的文件名(fsutil 需要作为输入)

改用dir /b /s

set count=fsutil hardlink list %%a | find /c /v ""

这不会将计数设置为任何合理的值。

使用另一个 for /f 并解析 fsutil 的输出,这样你就可以设置一个变量。

if %count% -EQU 1 del /Q %%a

这有两个错误。您需要使用延迟扩展才能正确评估 count。将 %count% 替换为 !count!。同时删除 -。将 -EQU 替换为 EQU.

试试下面的批处理文件。

test.cmd:

@echo off 
setlocal enabledelayedexpansion
set some_dir=C:\TEMP\
for /f %%a in ('dir /b /s %some_dir%') do (
  for /f %%b in ('fsutil hardlink list %%a ^| find /c /v ""') do (
    set count=%%b
    if !count! EQU 1 echo del /Q %%a        
    )
  )
endlocal

备注:

  • 如果您对结果满意,请删除 echo

示例用法和输出:

我使用 f:\test\folder1 作为我的测试目录。 hard 是指向 1.txt 的硬链接。

F:\test>dir f:\test\folder1
 Volume in drive F is Expansion
 Volume Serial Number is 3656-BB63

 Directory of f:\test\folder1

29/08/2016  21:40    <DIR>          .
29/08/2016  21:40    <DIR>          ..
21/08/2016  09:46                 0 1.txt
21/08/2016  09:46                 0 2.txt
21/08/2016  09:46                 0 3.txt
21/08/2016  09:46                 0 4.txt
21/08/2016  09:46                 0 5.txt
29/08/2016  21:38    <SYMLINK>      file [f:\d]
21/08/2016  09:46                 0 hard
29/08/2016  21:38    <SYMLINKD>     test [f:\d]
               7 File(s)              0 bytes
               3 Dir(s)  1,764,846,960,640 bytes free

F:\test>test
del /Q f:\test\folder1.txt
del /Q f:\test\folder1.txt
del /Q f:\test\folder1.txt
del /Q f:\test\folder1.txt
del /Q f:\test\folder1\file
del /Q f:\test\folder1\test

进一步阅读

简化方法:

@Echo Off
PushD X:\YourDirectory
For %%a In (*.*) Do (
    FSUtil HardLink List %%a|FindStr/VIC:"%%~pnxa">Nul||(Echo=Del "%%~a"))
Pause

如果您对输出感到满意,请删除第 5 行并从第 4 行中删除 'Echo='