1

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

非符号链接定义:除了使用命令 MKLINK /H 创建的文件之外的任何文件

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

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

当指定的 %file% 是符号链接时,它返回一个大于 1 的数字,当它只是一个简单文件时,它返回 1。到目前为止一切顺利!

当我需要自动化这个过程并获得这样的回报来比较它是否大于 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% 变量进行这种归因和比较吗?

4

3 回答 3

2

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

您的代码存在一些问题。

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

dir /b不起作用,因为它不返回具有完整路径的文件名(这是 的输入所必需的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!。同时删除-. 替换-EQUEQU

尝试以下批处理文件。

测试.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\2.txt
del /Q f:\test\folder1\3.txt
del /Q f:\test\folder1\4.txt
del /Q f:\test\folder1\5.txt
del /Q f:\test\folder1\file
del /Q f:\test\folder1\test

延伸阅读

于 2016-08-29T22:12:52.770 回答
1

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

  • 您需要延迟扩展,因为您在同一个带括号的代码块(即循环)中设置(写入)扩展(读取)变量;countfor /F %%a
  • 在您的for /F %%a循环中,您需要声明选项"eol=| delims=",以免遇到名称以开头的文件;(由于默认eol=;选项而将被忽略)和名称中包含空格的文件(您只会收到之前的位置由于默认delims SPACETAB默认选项的第一个空格tokens=1for /?有关详细信息,请参阅);
  • dir /B仅返回文件名,因此%%a实际上指向当前目录中的文件而不是C:\TEMP\; 要解决这个问题,只需先更改到该目录cd
  • 要捕获命令(行)的输出并将其分配给变量,请使用另一个for /F循环和set;这个循环将只迭代一次,因为find /C只返回一行;注意下面的转义管道^|,它要求不要立即执行它;
  • 没有比较运算符-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查询移到里面,从而避免定义一个辅助变量,这是我们唯一需要延迟扩展的变量。

于 2016-08-29T21:11:57.857 回答
0

简化方法:

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

当您对输出感到满意时,从第 4 行删除第 5 行和 'Echo='

于 2016-08-29T22:33:53.863 回答