如何使用Windowsbatch file检测(和删除)文件是否为空?

如何使用Windowsbatch file检测文件是否为空? 我想删除错误日志,如果他们是空的。

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

Solutions Collecting From Web of "如何使用Windowsbatch file检测(和删除)文件是否为空?"

您引用的链接使用以下来删除所有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" 

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

我花了一段时间把它弄出来,但现在它的工作原理:

 @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关闭)。 然后它将当前文件夹存储在topLevel变量中。 接下来是在当前文件夹和所有子文件夹中使用FOR命令遍历所有文件夹“%D”。 它将本地目录更改为找到的每个子文件夹(CD %% D)。 在使用另一个FOR循环的每个子文件夹中,它将查找并删除文件大小(对于%%〜zF为〜z)的所有文件%% 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/AD/OS') DO IF %%~zF EQU 0 (DEL "%%F") ELSE (GOTO :break) :break 

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

所以我修改了内部循环,以使用/ OS(Ordered Size)选项在DIR命令中按大小排序文件。 / AD选项不会列出目录,所以只剩下真实的文件(目录也被列为大小0,这就是为什么我加了这个)。 对于每个文件的大小进行检查。 一旦找到一个大于0字节的文件,就使用GOTO:break退出循环。 由于这些文件按大小排序,所以文件最小,安全可以像这样进行。 一个巨大的时间安排!

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

在我的大容量上似乎跑了几千倍的速度比以前更快 😉

我希望你喜欢它!

最好的问候,Axel Mertes

PS:DOS脚本中最大的噩梦就是理解你什么时候需要%%或者%,或者等等。

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

回声

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

删除

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

做你想做的事

我通常会用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 

简单的是找到文件中使用的行数

  findstr /R /N "^" file.txt | find /C ":" 

现在如果它的计数是零,则删除使用条件。

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