如何使用 Windows 批处理文件检测(并删除)文件为空?

发布于 2025-01-08 05:18:51 字数 428 浏览 1 评论 0原文

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

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

How do I detect if a file is empty using a Windows batch file? I want to delete error logs if they are empty.

I am aware for for loop solutions such as https://web.archive.org/web/20171110203759/http://anderwald.info/scripting/windows-batch-delete-all-empty-files-in-a-specified-folder/ but I was wondering if there was a more elegant solution if you know the specific single file in question that needs to be tested, as I may not wish to delete other zero byte files in the folder.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

ゝ杯具 2025-01-15 05:18:51

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

The link you cited used the following to delete all 0 length files

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

That is more complicated and not as efficient as it could be. It is much simpler to simply use:

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

You want to delete a specific file if it is zero length. So just substitute your file name for the * wild card.

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

If you are going to use this in a batch file than you need to double all the percents (%%F, %%~zF)

If you don't want to use a FOR loop, you can use a CALL parameter instead - it uses the same modifiers as FOR variables. However, CALL is slower than FOR (probably not significant in your case)

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

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

EDIT

I've thought of yet another way. A FINDSTR search string of "^" will match all lines of a file. But an empty file doesn't have any lines. So simply delete the file if FINDSTR fails to match a line.

>nul findstr "^" "yourFileName" || del "yourFileName"
杯别 2025-01-15 05:18:51

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

echo

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

delete

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

做你想做的事

The forfiles command might be nicer, like this:

echo

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

delete

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

Do what you want

扬花落满肩 2025-01-15 05:18:51

我已经成功制作了一个宏,它实际上可以删除文件夹层次结构中的空文件和空文件夹

我花了一段时间才弄明白,但现在它可以工作了:

@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 变量中。
接下来是使用当前文件夹和所有子文件夹中的 FOR 命令遍历所有文件夹“%D”。
它将本地目录更改为找到的每个子文件夹 (CD %%D)。
在每个子文件夹中,使用另一个 FOR 循环查找并删除文件大小(%%~zF 的 ~z)为 0 的所有文件 %%F。
当整个双循环完成时,所有空文件都被有效地从磁盘中删除。
现在执行一个新的 FOR 命令来执行 RD %%D 以删除每个目录。
由于 DOS 在这里是安全的,它只会删除空文件夹。里面有文件的文件夹保持完整。

但是,嘿,谁说你不能再改进一次?

我再次修改了脚本,现在大幅优化以实现快速处理

@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 循环触及了每个文件。由于空文件很少见,因此绝对没有必要触及每个文件,这会浪费大量时间。我尝试在包含约 500 万个文件的 25 TByte 卷上运行它。

因此,我修改了内部循环,使用 /OS(有序大小)选项在 DIR 命令中按大小对文件进行排序。 /AD 选项不列出目录,因此只保留真实文件(目录也被列为大小 0,这就是我添加此选项的原因)。对于每个文件,都会检查其大小。一旦找到大于 0 字节的文件,就会使用 GOTO :break 退出循环。由于文件是按大小排序的,最小的在前,因此这样操作是安全的。时间更安全!

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

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

我希望你喜欢它!

此致,
Axel Mertes

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

I've managed to make a macro that can actually delete empty files and empty folders within a folder hierarchy.

I took me a while to fiddle it out, but now it works:

@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"

It first disables echoing (remove @ECHO OFF if you want to read what actually happens).
Then it stores the current folder in topLevel variable.
Next is to walk trough all folders "%D" using the FOR command in the current folder and all sub folders.
It changes local directory to each of the sub folders found (CD %%D).
Within each sub folder using another FOR loop it finds and deletes all files %%F for which the filesize (~z for %%~zF) is 0.
When this entire dual loop is done all empty files are effectively killed from the disk.
Now a new FOR command is exectuted to perform a RD %%D to remove every directory.
Due to DOS being safe here it will delete only EMPTY folders. Folders with files inside keep intact.

But hey, who says you can't improve once more?

I've revamped the script once more, now heavily optimized for speedy processing:

@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

The problem with the previous one was that the two nested FOR loops touched every single file. As empty files are rare, there is absolutely no need to touch every file and its a big waste of time. I've tried to run it on a 25 TByte volume with ~5 million files..

So I modified the inner loop to sort files by size in a DIR command using the /OS (Ordered Size) option. The /A-D option does not list directories, so only true files remain (directories are listed as size 0 too, this is why I added this). For every file the size is checked. Once a file larger than 0 bytes is found, the loop is exited using the GOTO :break. As the files are sorted by size, smallest first, its safe to proceed like this. A huge timesafer!

As DOS FOR command has no elegant way to leave the loop I used this strange construct to call the inner loop using GOTO :break.

It seems to run about a few thousand times faster on my large volume than the previous one ;-)

I hope you like it!

Best regards,
Axel Mertes

PS: The biggest nightmare in DOS scripting is understanding when you need %% or %, ' or " etc.

尘曦 2025-01-15 05:18:51

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

I normally would create a vbscript file with the FileSystemObject that would handle the detection and deletion of the file, and run it from a batch file.

VBScript File:

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

For the Batch file:

cscript <filename>.vbs  
PAUSE
我早已燃尽 2025-01-15 05:18:51

简单的是使用 now 查找文件中的行数,

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

如果其计数为零,然后使用 if 条件删除。

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

simple is to find the number of lines in the file using

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

now if its count is zero then delete using if conditions.

you can use the loop through files and check for all files in folders

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文