Форум программистов, компьютерный форум, киберфорум
Batch (CMD/BAT)
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 5.00/5: Рейтинг темы: голосов - 5, средняя оценка - 5.00
2 / 2 / 1
Регистрация: 20.11.2021
Сообщений: 7

Ошибка (?) в алгоритме обработки маски файлов командами DEL, DIR и командлетами PowerShell

29.06.2022, 13:06. Показов 1176. Ответов 4

Студворк — интернет-сервис помощи студентам
Столкнулся с тем, что банальные команды "dir *.tmp" и "del *.tmp" отрабатывают не так, как ожидалось.
Вместо обработки маски [*.tmp] фактически обрабатывается маска [*.tmp*.].
Проверял на x64: Win 7 Pro, Win 10 Pro, Win Server 2019, Win Server 2022
На Win 7 так происходит на диске C: и D:
На Win 10 и Win Server 2019/2022 - так происходит только на диске С:, а на диске D:\ маска отрабатывает как и ожидается, то есть только как [*.tmp].
Разумных объяснений этому у меня нет...

Вот простой тест для демонстрации эффекта:
Windows Batch file
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@echo Off
cd /D "%~dp0"
md "%~dp0-test-"
echo 111>"%~dp0-test-\file1.tmp"
echo 111>"%~dp0-test-\file2.tmpl"
echo 111>"%~dp0-test-\file3.tmp.txt"
echo 111>"%~dp0-test-\file4.tmpl.txt"
dir /b "%~dp0-test-\*"
pause
dir /b "%~dp0-test-\*.tmp"
pause
del /Q /F /A "%~dp0-test-\*.tmp"
dir /b "%~dp0-test-\*"
pause
rd /Q /S "%~dp0-test-"
Вот что получается на экране:
Code
1
2
3
4
5
6
7
8
9
10
11
file1.tmp
file2.tmpl
file3.tmp.txt
file4.tmpl.txt
Для продолжения нажмите любую клавишу . . .
file1.tmp
file2.tmpl
Для продолжения нажмите любую клавишу . . .
file3.tmp.txt
file4.tmpl.txt
Для продолжения нажмите любую клавишу . . .
Подобное расширение маски в ряде случаев может быть критично.
У меня написано много батников, где выполняется DEL... Чтобы не переписывать все сразу, решил сделать в батнике функцию xDel с правильной обработкой маски - и вызывать ее вместо штатной команды DEL /A /Q /F.
Первой идеей была такая вставка на PowerShell:
Windows Batch file
1
2
3
4
5
call :xDel "%~dp0-test-" "*.tmp"
goto:eof
:xDel
    powershell Get-ChildItem -Force -File -LiteralPath '%~1' -Filter '%~2' ^| ForEach-Object { Remove-Item -Force -LiteralPath $_.fullname}
goto:eof
Оказалось, что это работает точно как штатная команда DEL, расширяя маску до [*.tmp*.] !
Попробовал так:
Windows Batch file
1
powershell Get-ChildItem -Force -File -LiteralPath '%~1' -Include '%~2' ^| ForEach-Object { Remove-Item -Force -LiteralPath $_.fullname}
Тоже расширяет маску!

Заработал такой вариант:
Windows Batch file
1
2
3
4
5
call :xDel "%~dp0-test-\*.tmp"
goto:eof
:xDel
    powershell Get-ChildItem -Force -File -Path '%~1' ^| ForEach-Object { Remove-Item -Force -LiteralPath $_.fullname}
goto:eof
Но возникла проблема с экранированием символов в -Path. Решил ее для []`'
Заодно сделал функцию xDelS, как эквивалент для DEL /A /Q /F /S.
Сейчас это работает так:

Windows Batch file
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
@echo Off
cd /D "%~dp0"
md "%~dp0-test-"
echo 111>"%~dp0-test-\file1.tmp"
echo 111>"%~dp0-test-\file2.tmpl"
echo 111>"%~dp0-test-\file3.tmp.txt"
echo 111>"%~dp0-test-\file4.tmpl.txt"
dir /b "%~dp0-test-\*"
pause
call :xDel "%~dp0-test-\*.tmp"
dir /b "%~dp0-test-\*"
pause
rd /Q /S "%~dp0-test-"
goto:eof
 
:xDel
    setlocal
    set xMask=%xMask:[=`[%
    set xMask=%xMask:]=`]%
    set xMask=%xMask:``=````%
    set xMask=%xMask:'=''%
    powershell Get-ChildItem -Force -File -Path '%xMask%' ^| ForEach-Object { Remove-Item -Force -LiteralPath $_.fullname}
goto:eof
 
:xDelS
    setlocal
    set xMask=%xMask:[=`[%
    set xMask=%xMask:]=`]%
    set xMask=%xMask:``=````%
    set xMask=%xMask:'=''%
    powershell Get-ChildItem -Force -File -Recurse -Path '%xMask%' ^| ForEach-Object { Remove-Item -Force -LiteralPath $_.fullname}
goto:eof
Вот что получается на экране:
Code
1
2
3
4
5
6
7
8
9
file1.tmp
file2.tmpl
file3.tmp.txt
file4.tmpl.txt
Для продолжения нажмите любую клавишу . . . 
file2.tmpl
file3.tmp.txt
file4.tmpl.txt
Для продолжения нажмите любую клавишу . . .
Вроде работает, но возможно еще что-то надо экранировать...
Ура?... Но все это больше похоже не на кодинг, а на какой-то костылинг...

Кроме того, очевидно, затронуты и другие команды, использующие выбор файлов по маске.
К примеру type *.tmp отрабатывает маску как [*.tmp*.]
Переписывать их все - смысла никакого. Хотя, конечно, не все они нужны и/или критичны.

Постепенно переписал бы все на PowerShell, но костыли с экранированием тоже как-то напрягли.

Не очень понимаю почему, но ничего о подобной "расширенной" трактовке маски не нагуглилось.
А ведь судя по тому, что и на Win 7 так работает, это достаточно давняя история.

Конечно, можно пересмотреть каждый батник (хотя у меня их сильно за сотню), выявить, где обработка маски может обернуться проблемой и решать в каждом случаи, что делать.
Но, если уж все перелопачивать, хотелось бы с большим смыслом.

Собственно вопросы:
1) Есть какие-то идеи, почему маски так странно обрабатываются? Это "бага или фича"? Может, это где-то описано?
2) Есть ли варианты как-то это обойти малой кровью, не переписывая все батники на чем-то другом?
3) Есть ли возможность какой-то магией заставить PowerShell отрабатывать маску всегда однозначно?
4) Если вариантов, кроме как переписать батники, нет - то какой скриптовый язык стоит посмотреть?

Добавлено через 1 час 37 минут
Оказалось, что forfiles нормально обрабатывает маску вида [*.tmp], не расширяет.
Вариант замены DEL без PowerShell, вывод на экран отсутствует.
Windows Batch file
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@echo Off
call :xDel "%~dp0-test-" "*.tmp"
goto:eof
 
:xDel [Path] [FileName Mask]
    set xPath=%~1
    rem Double the slash at the end of хPath, if there is one there
    if %xPath:~-1%==\ set xPath=%xPath%\
    forfiles.exe /P "%xPath%" /M "%~2" /C "cmd /c if @isdir==FALSE del /Q /A /F @path ^>nul" 2>nul
goto:eof
 
:xDelS [Path] [FileName Mask]
    set xPath=%~1
    rem Double the slash at the end of хPath, if there is one there
    if %xPath:~-1%==\ set xPath=%xPath%\
    forfiles.exe /S /P "%xPath%" /M "%~2" "cmd /c if @isdir==FALSE del /Q /A /F @path ^>nul" 2>nul
goto:eof
0
Лучшие ответы (1)
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
29.06.2022, 13:06
Ответы с готовыми решениями:

Работа с командлетами MS PowerShell
Разработать командлет для нахождения среди выполняющихся процессов имен трех процессов, работающих в системе дольше всего

Средство обработки копий файлов PowerShell
Здравствуйте, ищу помощь по данному заданию: Разработать программу в командной среде Powershell, позволяющую анализировать заданное...

Есть ли различия между командами DEL и ERASE?
Ребят, не как не могу найти информацию о различии команды del и erase, помогите пожалуйста

4
 Аватар для Angry Old Man
3045 / 747 / 313
Регистрация: 26.03.2022
Сообщений: 1,397
Записей в блоге: 1
29.06.2022, 13:32
Цитата Сообщение от CyberFun2 Посмотреть сообщение
Это "бага или фича"?
Описанный баг - это фича. Спотыкался сам, но объяснений не искал.
Windows Batch file
1
2
dir /B *.xls |findstr /E /I ".xls"
where "Z:\Box_In\Тра ля ля:*.xls"
Windows Batch file
1
2
3
@Echo Off
        For /f "delims=" %%f In ('2^>nul where /F "Z:\Box_In\Box_In\Тра ля ля:*.xls"') Do Del %%f
Exit /B
1
2 / 2 / 1
Регистрация: 20.11.2021
Сообщений: 7
29.06.2022, 14:03  [ТС]
Спасибо! Работает. Только добавил ключ, чтобы папки убрать из выдачи dir:
dir /A:-D и далее по тексту

Цитата Сообщение от Angry Old Man Посмотреть сообщение
В действительности всё не так, как на самом деле.
Вот уж точно ! )
0
2 / 2 / 1
Регистрация: 20.11.2021
Сообщений: 7
30.06.2022, 13:20  [ТС]
xcopy, copy, robocopy - аналогично трактуют маску "расширенно", то есть как [*.tmp*.]

Также обнаружился глюк с файлами вида "*.", где точка присутствует в явном виде, а после нее ничего нет.
copy пропускает при копировании файлы "*.", сообщая "Не удается найти указанный файл"
xcopy прерывает копирование и завершается при попытке копирования файла "*.", сообщая "Не удается найти указанный файл"
robocopy - копирует

Добавлено через 1 час 15 минут
del * удаляет встречающиеся файлы вида [*.], но если удалять по одному - не удаляет (Не удается найти файл)
Например, файл "11." не будет удален командой del 11.
0
2 / 2 / 1
Регистрация: 20.11.2021
Сообщений: 7
03.07.2022, 20:39  [ТС]
Лучший ответ Сообщение было отмечено FlasherX как решение

Решение

RTFM...
Такое поведение DIR описано в документации.
Поиск идет в том числе по коротким именам (8.3), поэтому под маску [*.tmp] реально попадают [*.tmp*.], ведь в именах 8.3 сохраняются только 3 символа в расширении.
Очевидно, остальные команды, трактующие маску расширенно, тоже учитывают имена формата 8.3
Посмотреть короткие имена можно dir /x
https://docs.microsoft.com/ru-... mmands/dir

В принципе, на томах NTFS есть возможность отключить ведение имен вида 8.3 и удалить все такие имена.
В этом случаи DIR работает только с длинными именами и маски вида *.tmp выбирают файлы в строгом соответствии с маской.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
03.07.2022, 20:39
Помогаю со студенческими работами здесь

Командами строковой обработки
Объясните пожалуйста на очень нубовском языке принцип действия комманд: MOVSB – Копирование строки байт MOVSW – Копирование строки слов...

Задать корректный паттерн для обработки маски из селекторов
Привет! Необходимо корректно задать паттерн, который бы разбивал заданную маску (обычную строку вида 'a.nav-bar#top-nav') на массив с...

Маски имён файлов
Для групповых операций с файлами используются маски имён файлов. Маска представляет собой последовательность букв, цифр и прочих допустимых...

Задание маски файлов
нужно задать так, что бы любые файлы считывало с определенной папки... делал так AnsiString Path1 = "file\\"; int done =...

Задание точной маски файлов
Есть директория в которую сыпятся файлы с разными масками, которые в зависимости от их маски должны копироваться или переноситься по...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
5
Ответ Создать тему
Новые блоги и статьи
Вывод диалогового окна перед закрытием, если документ не проведён
Maks 04.04.2026
Алгоритм из решения ниже реализован на примере нетипового документа "СписаниеМатериалов", разработанного в конфигурации КА2. Задача: реализовать программный контроль на предмет проведения документа. . .
Программный контроль заполнения реквизита табличной части документа
Maks 02.04.2026
Алгоритм из решения ниже реализован на примере нетипового документа "СписаниеМатериалов", разработанного в конфигурации КА2. Задача: реализовать контроль заполнения реквизита "ПричинаСписания". . .
wmic не является внутренней или внешней командой
Maks 02.04.2026
Решение: DISM / Online / Add-Capability / CapabilityName:WMIC~~~~ Отсюда: https:/ / winitpro. ru/ index. php/ 2025/ 02/ 14/ komanda-wmic-ne-naydena/
Программная установка даты и запрет ее изменения
Maks 02.04.2026
Алгоритм из решения ниже реализован на примере нетипового документа "СписаниеМатериалов", разработанного в конфигурации КА2. Задача: при создании документов установить период списания автоматически. . .
Вывод данных в справочнике через динамический список
Maks 01.04.2026
Реализация из решения ниже выполнена на примере нетипового справочника "Спецтехника" разработанного в конфигурации КА2. Задача: вывести данные из ТЧ нетипового документа. . .
Программное заполнения текстового поля в реквизите формы документа
Maks 01.04.2026
Алгоритм из решения ниже реализован на нетиповом документе "ВыдачаОборудованияНаСпецтехнику" разработанного в конфигурации КА2, в дополнении к предыдущему решению. На форме документа создается. . .
К слову об оптимизации
kumehtar 01.04.2026
Вспоминаю начало 2000-х, университет, когда я писал на Delphi. Тогда среди программистов на форумах активно обсуждали аккуратную работу с памятью: нужно было следить за переменными, вовремя. . .
Идея фильтра интернета (сервер = слой+фильтр).
Hrethgir 31.03.2026
Суть идеи заключается в том, чтобы запустить свой сервер, о чём я если честно мечтал давно и давно приобрёл книгу как это сделать. Но не было причин его запускать. Очумелые учёные напечатали на. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru