我正在使用以下批处理脚本,同时删除了一定大小以下的文件。
@echo off
setlocal
:: Size is in bytes
set "min.size=100000"
for /f "usebackq delims=;" %%A in (`dir /b /A:-D *.*`) do If %%~zA LSS %min.size% del "%%A"
如果我将批处理文件放在文件夹中,但它也删除了该批处理文件,这将起作用。
但是如何将批处理文件保留在其他位置并显式指定目录路径?
答案 0 :(得分:3)
最简单的解决方案是将要删除文件(例如C:\Temp\Test
)的目录临时设置为活动目录。
@echo off
setlocal EnableExtensions DisableDelayedExpansion
rem Size is in bytes
set "min.size=100000"
set "FullBatchFileName=%~f0"
pushd "C:\Temp\Test"
rem Do nothing if the command line above fails unexpected.
if errorlevel 1 goto EndBatch
for /F "eol=| delims=" %%I in ('dir * /A-D-H /B /OS 2^>nul') do if not "%FullBatchFileName%" == "%%~fI" if %%~zI LSS %min.size% ( del "%%I" ) else goto DeletionDone
:DeletionDone
popd
:EndBatch
endlocal
DIR 命令行由 FOR 执行,该命令在以cmd.exe /C
为背景的单独命令过程中执行,并且 FOR 捕获所有 DIR 输出的行以处理 STDOUT 。在发现当前目录中没有任何未隐藏文件的情况下, DIR 输出的用于处理 STDERR 的错误消息已通过2>nul
重定向到设备 NUL 抑制它。
也请阅读有关Using Command Redirection Operators的Microsoft文章,以获取2>nul
的解释。当Windows命令解释器在执行命令之前处理此命令行时,重定向操作符>
必须在 FOR 命令行上使用脱字符号^
进行转义,才能被解释为文字字符。 FOR ,它将在后台启动的单独命令进程中执行嵌入式dir
命令行。
DIR 选项/OS
导致获得 DIR 输出的未隐藏文件的列表,该列表按大小排在最前,最后排在最后。>
FOR 将跳过以分号开头的行,这意味着它将跳过文件名以;
开头的文件,通常这是可能的。通过使用eol=|
将竖线指定为行尾字符(文件名不能包含)可以避免这种情况。
FOR 将使用普通空格和水平制表符作为分隔符将行分成子字符串,并且仅将第一个子字符串分配给循环变量I
。文件名可以包含一个或多个空格。因此,delims=
用于定义一个空的分隔符列表,这些分隔符将完全禁用行拆分行为,并被分配给循环变量I
的整个文件名。
IF 条件if not "%FullBatchFileName%" == "%%~fI"
将区分大小写的批处理文件的全限定名(驱动器+路径+名称+扩展名)与当前文件的全限定名进行比较。如果当前文件不是当前正在运行的批处理文件,则此条件仅 true 。
下一个 IF 条件if %%~zI LSS %min.size%
将转换为32位带符号整数的当前文件的文件大小与也转换为32位带符号整数的指定文件大小进行比较。对于2个GiB或更大的文件,此文件大小比较失败,因为这样的大文件超过了最大正32位有符号整数值2147483647。
由于 DIR 输出的所有其他文件,在第一行的{strong> FOR 循环以第一行goto DeletionDone
退出,该文件的大小等于或大于指定的最小大小。文件大小绝对等于或大于指定的最小大小,因为它是按大小从小到大的顺序输出的。
要了解所使用的命令及其工作方式,请打开命令提示符窗口,在其中执行以下命令,并非常仔细地阅读每个命令显示的所有帮助页面。
call /?
...说明%~f0
...参数0的完全限定文件名-当前执行的批处理文件。dir /?
echo /?
endlocal /?
for /?
goto /?
if /?
popd /?
pushd /?
rem /?
set /?
setlocal /?
答案 1 :(得分:1)
如果您想继续使用PowerShell,可以使用以下脚本。如果您确信将删除正确的文件,请从-WhatIf
cmdlet中删除Remove-Item
。
$deldir = 'C:\Temp'
$minsize = 100000
$precious = 'Remove-UnderSize.ps1', 'Remove-UnderSize.bat'
Get-ChildItem -File -Path $deldir |
ForEach-Object {
if (-not ($precious -contains $_.Name)) {
if ($_.Length -lt $minsize) {
Remove-Item -Path $_.FullName -WhatIf
}
}
}
可以从cmd.exe bat文件脚本中调用此脚本。
powershell -NoProfile -File .\Remove-UnderSize.ps1