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

Xon*_*ron 14 windows cmd batch-file

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

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

dbe*_*ham 28

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

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

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

for %F in (*) do if %~zF equ 0 del "%F"
Run Code Online (Sandbox Code Playgroud)

如果长度为零,则要删除特定文件.所以只需用你的文件名替换*外卡.

for %F in ("yourFileName") do if %~zF equ 0 del "%F"
Run Code Online (Sandbox Code Playgroud)

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

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

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

:deleteIfEmpty
if %~z1 eq 0 del %1
exit /b
Run Code Online (Sandbox Code Playgroud)

编辑

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

>nul findstr "^" "yourFileName" || del "yourFileName"
Run Code Online (Sandbox Code Playgroud)


小智 5

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

回声

forfiles /c "cmd /c if @fsize==0  echo @file"
Run Code Online (Sandbox Code Playgroud)

删除

forfiles /c "cmd /c if @fsize==0  del @file"
Run Code Online (Sandbox Code Playgroud)

做你想做的


Axe*_*tes 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"
Run Code Online (Sandbox Code Playgroud)

它首先禁用回显(如果要阅读实际情况,请删除@ECHO OFF)。然后将当前文件夹存储在topLevel变量中。接下来是使用当前文件夹和所有子文件夹中的FOR命令来遍历所有文件夹“%D”。它将本地目录更改为找到的每个子文件夹(CD %% D)。在每个子文件夹中,使用另一个FOR循环查找并删除文件大小(%z〜zF的〜z)为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
Run Code Online (Sandbox Code Playgroud)

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

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

由于DOS FOR命令没有退出循环的优雅方法,因此我使用了这种奇怪的构造,使用GOTO:break调用了内部循环。

在我的大容量文件上,它的运行速度似乎比上一个快了几千倍;-)

我希望你喜欢它!

最好的问候,Axel Mertes

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


Dav*_*ker 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
Run Code Online (Sandbox Code Playgroud)

对于批处理文件:

cscript <filename>.vbs  
PAUSE
Run Code Online (Sandbox Code Playgroud)