Как определить (и удалить) файл, если он пуст, используя пакетный файл Windows?
Как определить, пустой ли файл с использованием командного файла Windows? Я хочу удалить журналы ошибок, если они пусты.
Я знаю, что для решений loop, таких как http://anderwald.info/scripting/windows-batch-delete-all-empty-files-in-a-specified-folder/, но мне было интересно, было ли более элегантное решение, если вы знаете конкретные отдельный файл, который должен быть протестирован, так как я не хочу удалять другие файлы с нулевым байтом в папке.
Ответы
Ответ 1
Ссылка, которую вы указали, использовала следующее, чтобы удалить все файлы длиной 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"
Вы хотите удалить определенный файл, если он равен нулю. Поэтому просто замените свое имя файла для *
wild card.
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"
Ответ 2
Команда forfiles
может быть приятнее, например:
эхо
forfiles /c "cmd /c if @fsize==0 echo @file"
удалить
forfiles /c "cmd /c if @fsize==0 del @file"
Сделайте то, что хотите
Ответ 3
Мне удалось создать макрос, который на самом деле может удалять пустые файлы и пустые папки в иерархии папок.
Я взял время, чтобы поиграть, но теперь он работает:
@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 находит и удаляет все файлы %% F, для которых размер файла (~ z для %% ~ zF) равен 0.
Когда весь этот двойной цикл выполняется, все пустые файлы эффективно уничтожаются с диска.
Теперь вызывается новая команда FOR для выполнения RD %% D для удаления всех каталогов.
Из-за того, что DOS безопасен, он удаляет только папки EMPTY. Папки с файлами внутри остаются неповрежденными.
Но эй, кто говорит, что не можешь улучшить еще раз?
Я обновил script еще раз, теперь сильно оптимизирован для быстрой обработки:
@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-битном томе с ~ 5 миллионами файлов.
Итак, я изменил внутренний цикл, чтобы сортировать файлы по размеру в команде DIR, используя параметр /OS (Ordered Size). Параметр /A -D не отображает каталоги, поэтому остаются только истинные файлы (каталоги также перечислены как размер 0, поэтому я добавил это). Для каждого файла размер проверяется. После того, как найден файл размером более 0 байтов, цикл завершается с помощью GOTO: break. Поскольку файлы сортируются по размеру, наименьшим первым, безопасно действовать следующим образом. Огромное время!
Поскольку команда DOS FOR не имеет элегантного способа выйти из цикла, я использовал эту странную конструкцию для вызова внутреннего цикла с использованием GOTO: break.
Кажется, он работает в в несколько тысяч раз быстрее на моем большом объеме, чем предыдущий, -)
Надеюсь, вам понравится!
С уважением,
Аксель Мертес
PS: Самый большой кошмар в сценариях DOS - это понимание, когда вам нужно %% или%, 'или' и т.д.
Ответ 4
Я обычно создавал бы файл vbscript с файловым файлом FileSystemObject, который обрабатывал бы обнаружение и удаление файла и запускал его из пакетного файла.
Файл 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
Ответ 5
simple - найти количество строк в файле, используя
findstr /R /N "^" file.txt | find /C ":"
теперь, если его счет равен нулю, тогда удалите с использованием условий if.
вы можете использовать цикл через файлы и проверять все файлы в папках