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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/9378972/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-09 09:15:41  来源:igfitidea点击:

How do I Detect (and Delete) a File if it is Empty using a Windows Batch File?

windowsbatch-filecmd

提问by Xonatron

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

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

I am aware for for loop solutions such as 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.

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

回答by dbenham

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

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

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)

如果要在批处理文件中使用它,则需要将所有百分比 ( %%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)

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

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

我又想了一个办法。FINDSTR 搜索字符串"^"将匹配文件的所有行。但是一个空文件没有任何行。因此,如果 FINDSTR 无法匹配一行,只需删除该文件。

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

回答by joel Xu

The forfilescommand might be nicer, like this:

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

echo

回声

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

delete

删除

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

Do what you want

做你想做的

回答by Axel Mertes

I've managed to make a macro that can actually delete empty files and empty folderswithin 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.

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

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

但是,嘿,谁说你不能再提高一次?

I've revamped the script once more, now heavily optimizedfor 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..

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

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!

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

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.

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

It seems to run about a few thousand times fasteron 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.

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

回答by Ashish

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.

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

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

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

回答by David Welker

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.

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

VBScript File:

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

For the Batch file:

对于批处理文件:

cscript <filename>.vbs  
PAUSE