如何使用Windows批处理文件检测文件是否为空?我想删除错误日志,如果它们是空的。
我知道for循环解决方案,例如http://anderwald.info/scripting/windows-batch-delete-all-empty-files-in-a-specified-folder/,但我想知道是否有更优雅的解决方案,如果您知道需要测试的特定单个文件,因为我可能不希望删除文件夹中的其他零字节文件。
答案 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条件删除。
您可以使用循环文件并检查文件夹中的所有文件