如果使用Windows批处理文件将文件清空,如何检测(和删除)文件?

时间:2012-02-21 14:09:20

标签: windows batch-file cmd

如何使用Windows批处理文件检测文件是否为空?我想删除错误日志,如果它们是空的。

我知道for循环解决方案,例如http://anderwald.info/scripting/windows-batch-delete-all-empty-files-in-a-specified-folder/,但我想知道是否有更优雅的解决方案,如果您知道需要测试的特定单个文件,因为我可能不希望删除文件夹中的其他零字节文件。

5 个答案:

答案 0 :(得分:27)

您引用的链接使用以下内容删除所有0个长度的文件

for /F "delims=" "%I" in ('dir /B') do if not exist "%I\" if %~zI EQU 0 del "%I"

这更复杂,效率也不尽如人意。简单地使用它简单得多:

for %F in (*) do if %~zF equ 0 del "%F"

如果长度为零,则要删除特定文件。所以只需用*通配符替换你的文件名。

for %F in ("yourFileName") do if %~zF equ 0 del "%F"

如果要在批处理文件中使用此项,则需要将所有百分比加倍(%%F%%~zF

如果您不想使用FOR循环,则可以使用CALL参数 - 它使用与FOR变量相同的修饰符。但是,CALL比FOR慢(在您的情况下可能不重要)

@echo off
call :deleteIfEmpty "yourFileName"
exit /b

:deleteIfEmpty
if %~z1 eq 0 del %1
exit /b

修改

我想到了另一种方式。 FINDSTR搜索字符串"^"将匹配文件的所有行。但是空文件没有任何行。因此,如果FINDSTR与一行不匹配,只需删除该文件。

>nul findstr "^" "yourFileName" || del "yourFileName"

答案 1 :(得分:5)

forfiles命令可能更好,如下所示:

回声

forfiles /c "cmd /c if @fsize==0  echo @file"

删除

forfiles /c "cmd /c if @fsize==0  del @file"

做你想做的事

答案 2 :(得分:5)

我设法制作了一个宏,可以在文件夹层次结构中实际删除空文件和空文件夹

我花了一些时间把它弄出来,但现在它起作用了:

@ECHO OFF
SET topLevel=%cd%
FOR /D /R %%D IN (*) DO ( 
  CD %%D
  FOR %%F IN (*) DO IF %%~zF EQU 0 DEL "%%F"
)
CD %topLevel%
FOR /F "usebackq delims=" %%D IN (`"DIR/AD/B/S|SORT/R"`) DO RD "%%D"

它首先禁用回显(如果你想阅读实际发生的事情,请删除@ECHO OFF)。 然后它将当前文件夹存储在topLevel变量中。 接下来是走遍所有文件夹"%D"在当前文件夹和所有子文件夹中使用FOR命令。 它将本地目录更改为找到的每个子文件夹(CD %% D)。 在使用另一个FOR循环的每个子文件夹中,它查找并删除文件大小(〜%为%% ~zF)为0的所有文件%% F. 当完成整个双循环时,所有空文件都有效地从磁盘中被杀死。 现在,将执行新的FOR命令以执行RD %% D以删除每个目录。 由于DOS安全,它将只删除EMPTY文件夹。内部文件的文件夹保持不变。

但嘿,谁说你再也不能提高?

我再次修改了剧本,现在严重优化以便快速处理

@ECHO OFF
SET topLevel=%CD%
FOR /D /R %%D IN (*) DO (
  CD %%D 
  CALL :innerLoop
)
CD %topLevel%
FOR /F "usebackq delims=" %%D IN (`"DIR /AD/B/S | SORT /R"`) DO RD "%%D"
GOTO :break

:innerLoop
  FOR /F "delims=" %%F IN ('DIR/B/A-D/OS') DO IF %%~zF EQU 0 (DEL "%%F") ELSE (GOTO :break)

:break

前一个问题是两个嵌套的FOR循环触及了每个文件。由于空文件很少,因此绝对不需要触摸每个文件,这是浪费大量时间。我尝试在25 TB的卷上运行它,文件大约有500万..

所以我修改了内部循环,使用/ OS(Ordered Size)选项在DIR命令中按大小对文件进行排序。 / A-D选项不列出目录,因此只保留真实文件(目录也列为大小0,这就是我添加此内容的原因)。对于每个文件,检查大小。找到大于0字节的文件后,使用GOTO:break退出循环。由于文件按大小排序,最小,因此可以像这样安全地进行。一个巨大的时代!

由于DOS FOR命令没有优雅的方式离开循环我使用这个奇怪的构造使用GOTO调用内循环:break。

在我的大音量上似乎比前一个快了几千倍; - )

我希望你喜欢它!

祝你好运, Axel Mertes

PS:DOS脚本中最大的噩梦就是理解何时需要%%或%,'或"等。

答案 3 :(得分:1)

我通常会使用FileSystemObject创建一个vbscript文件来处理文件的检测和删除,并从批处理文件中运行它。

VBScript文件:

Dim oFSO
Dim oFile
Dim ts
strFilePath = "<insert path to file here>"
Set oFSO = CreateObject("Scripting.FileSystemObject")
if oFSO.FileExists(strFilePath) then
   Set oFile = oFSO.GetFile(strFilePath)
   strLine = ""
   linecount = 0
   blnShouldDelete = True
   Set ts = oFile.OpenAsTextStream(1, -2)
   Do While ts.AtEndOfStream <> True
      linecount = linecount + 1
      strLine = ts.ReadLine

      if Len(strLine) > 0 then
         blnShouldDelete = False
      end if 
   Loop
   ts.Close

   if (linecount = 0 Or linecount = 1) And blnShouldDelete = True then
       oFile.Delete
   end if
end if
set oFSO = Nothing

批处理文件:

cscript <filename>.vbs  
PAUSE

答案 4 :(得分:1)

简单就是使用

查找文件中的行数
   findstr /R /N "^" file.txt | find /C ":"

现在如果其计数为零,则使用if条件删除。

您可以使用循环文件并检查文件夹中的所有文件