Имя пользователя:
Пароль:  
Помощь | Регистрация | Забыли пароль?  | Правила  

Компьютерный форум OSzone.net » Программирование, базы данных и автоматизация действий » Скриптовые языки администрирования Windows » CMD/BAT - Определение и работа с некорректными именами файлов

Ответить
Настройки темы
CMD/BAT - Определение и работа с некорректными именами файлов

Новый участник


Сообщения: 6
Благодарности: 0

Профиль | Отправить PM | Цитировать


Изменения
Автор: ChimMAG
Дата: 17-11-2021
Описание: -
CMD очень не любит имена файлов со всякими !, скобками и прочими символами. Но если попадаются такие - хотелось бы их если не обрабатывать, то хотя бы сообщать скрипту об этом. По конкретике:
Код: Выделить весь код
for /R %%a in (.) do (set TKatD="%%a"&if "%%a"==!TKatD! (call :ObrabKat))
exit /b

:ObrabKat
echo %TKatD%
set TKat=%TKatD%
exit /b
Что имеем в трассировке:
Код: Выделить весь код
C:\Users\1\Temp\MS-DOS_Flash>(set TKatD="C:\Users\1\Temp\MS-DOS_Flash\!!!MS-DOS-ver.5-7 (ms-dos.biz)!!!\."  & if "C:\Users\1\Temp\MS-DOS_Flash\!!!MS-DOS-ver.5-7 (ms-dos.biz)!!!\." == !TKatD! (call :ObrabKat ) ) 

C:\Users\1\Temp\MS-DOS_Flash>echo "C:\Users\1\Temp\MS-DOS_Flash\\." 
"C:\Users\1\Temp\MS-DOS_Flash\\."

C:\Users\1\Temp\MS-DOS_Flash>set TKat="C:\Users\1\Temp\MS-DOS_Flash\\."
Поясняю: команда FOR нормально обрабатывает косячное имя файла, переменная %%a имеет именно это имя. Более того, так как корректно обрабатывается условный переход, то и !TKatD! тоже равен %%a (собственно этот условный переход и был на такой случай расчитан). Но после того, как переходим и просто сразу выводим значение %TKatD% - в нём обрезаются !!! и всё, что между ними. Почему так или как-то можно отследить это?

Далее мне надо войти в данный каталог и уже в нём прошустрить файлы. И, само собой, команда
Код: Выделить весь код
cd %TKatD%
не обрабатывается корректно. Тут попытался выйти из положения втавив туда, где имя каталога ещё полное - (cd %%a) - трассировка пишет, что подставляется в строку вроде то, но нет, не срабатывает такой фокус, не заходит.

P.S. Уже на моменте написания я нашёл частичное решение - сравнение нашей переменной и текущего каталога
Код: Выделить весь код
if not %TKat%=="%CD%\" (exit /b)
- в этом случае хотя бы пропускается косячные. Но всё равно общий вопрос - почему так происходит остаётся открытым.

Отправлено: 15:25, 17-11-2021

 

Ветеран


Contributor


Сообщения: 2708
Благодарности: 1684

Профиль | Отправить PM | Цитировать


Цитата ChimMAG:
CMD очень не любит имена файлов со всякими !, скобками и прочими символами. Почему так или как-то можно отследить это? »
Надо правильно их употреблять. Потому что Вы используете EnableDelayedExpansion, что предполагает наличие переменных в !!. Соответственно, при обработке строк то, что встречается в !! интерпретируется как переменная с непредсказуемыми последствиями. Выкручивайтесь как-нибудь без EnableDelayedExpansion - уверяю, это возможно. Изложите, чего Вы домогаетесь, можно тогда советовать конкретнее: по обрывкам кода без четкой постановки трудновато, конструкция
(set TKatD="%%a"&if "%%a"==!TKatD! (call :ObrabKat))
меня угнетает, я её не понимаю. Как возможный приём (не решение, только как пример):
Код: Выделить весь код
@Echo Off
cls
	Set "TKatD=!!!MS-DOS-ver.5-7 (ms-dos.biz)!!!"
	For /R %%d In (.) Do Echo %%d |>nul 2>&1 FindStr /I "\%TKatD%\" &&Call :ObrabKat "%%d"
Pause
Exit /B

:ObrabKat
	Echo %1
	Dir %1 /s /b /A:-D
Exit /B
Код: Выделить весь код
@Echo Off
cls
	For /R %%d In (.) Do (
		Set "TKatD=%%d" 
		Call Echo "%%TKatD%%"
		Call :ObrabKat "%%d" "%%TKatD%%"
	)
Pause
Exit /B

:ObrabKat
	If %1==%2 Echo Ура!  %1  %2 
Exit /B
Помимо этого, если в имени файла встречается символ не из 866 кодовой страницы, иногда помогает при этом chcp 1251. Надо конкретика задачи.

-------
Даже самая сложная проблема обязательно имеет простое, лёгкое для понимания, неправильное решение. Каждое решение плодит новые проблемы.


Последний раз редактировалось megaloman, 17-11-2021 в 17:10.


Отправлено: 16:24, 17-11-2021 | #2



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

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


Новый участник


Сообщения: 6
Благодарности: 0

Профиль | Отправить PM | Цитировать


Цитата megaloman:
конструкция
(set TKatD="%%a"&if "%%a"==!TKatD! (call :ObrabKat))
меня угнетает, я её не понимаю. Как возможный приём (не решение, только как пример): »
Я увидел, что в случае такого странного каталога переменная TKatD далее урезана, а в переменной %%a - полное имя и логика была такая, что, возможно, при присваивании переменная "ломается" и это должно было отсечь такие случаи и не обрабатывать дальше такой каталог. Но это не работает, этот if я убираю, оставляю только call.

С EnableDelayedExpansion - наверное действительно в данном конкретном случае поможет, завтра поэсперементирую. А как быть в случае наличия в имени файла скобки ( ? Скрипт не завершится с ошибкой?

Отправлено: 17:21, 17-11-2021 | #3


Ветеран


Сообщения: 27449
Благодарности: 8086

Профиль | Отправить PM | Цитировать


ChimMAG, лучше вообще не использовать языки подобные CMD и PowerShell, если есть сложная обработка имён.
Это сообщение посчитали полезным следующие участники:

Отправлено: 17:40, 17-11-2021 | #4


Забанен


Сообщения: 346
Благодарности: 64

Профиль | Цитировать


Код: Выделить весь код
Echo on

cd /d "%~dp0"

for /F %%a in ('dir /b /s') do ( ...........делай что хочешь с каталогом....... )

exit /b
не, фигня...
можно так(только в цикле учитывать что появится доп."слэш" в конце и убирать его):
Код: Выделить весь код
@echo on
chcp 65001
for /r %%a in (\) do ( echo %%a )
pause
exit
у мя выводит вроде ↓
Код: Выделить весь код
for /R %a in (\) do (echo %a  )

(echo C:\Activators\\  )
C:\Activators\\

(echo C:\Activators\!!!MS-DOS-ver.5-7 (ms-dos.biz)!!!\\  )
C:\Activators\!!!MS-DOS-ver.5-7 (ms-dos.biz)!!!\\

(echo C:\Activators\KMSAuto Net 2015 v1.4.2 Portable\\  )
C:\Activators\KMSAuto Net 2015 v1.4.2 Portable\\

(echo C:\Activators\KMSAuto Net 2015 v1.4.2 Portable\readme\\  )
C:\Activators\KMSAuto Net 2015 v1.4.2 Portable\readme\\

(echo C:\Activators\kmsauto-office\\  )
C:\Activators\kmsauto-office\\

Отправлено: 17:46, 17-11-2021 | #5


Новый участник


Сообщения: 6
Благодарности: 0

Профиль | Отправить PM | Цитировать


Цитата wasp14:
у мя выводит вроде »
Ещё раз - внутри цикла for всё выводит. Но если я через call начинаю работать с переменными ВНЕ цикла, то всё обрезается. Попробуйте такую конструкцию:
Код: Выделить весь код
for /R %a in (\) do (set X=%%a&call :Obrab )
exit /b

:Obrab
echo %X%
exit /b
Цитата Iska:
ChimMAG, лучше вообще не использовать языки подобные CMD и PowerShell, если есть сложная обработка имён. »
Так-то согласен... Но сложной обработки имён нет, есть несознательные граждане, которые обзывают файлы как бог на душу придётся (я не про приведённый пример, это просто в тестовом каталоге встретилось), из-за чего скрипты ломаются при любой операции... :-(

Отправлено: 04:56, 18-11-2021 | #6


Аватара для DJ Mogarych

fascinating rhythm


Moderator


Сообщения: 6491
Благодарности: 1465

Профиль | Отправить PM | Цитировать


В Powershell есть параметр -LiteralPath, помогает в таких случаях.

-------
Powershell 7.x | Powershell 5.1 | ffmpeg (docs)


Отправлено: 09:54, 18-11-2021 | #7


Ветеран


Contributor


Сообщения: 2708
Благодарности: 1684

Профиль | Отправить PM | Цитировать


ChimMAG, В вашем примере переменная %X% внутри цикла, хоть Вы ее хотите использовать в процедуре. Поэтому, если аккуратно, то вот так разными способами и ничего не обрезается и не ломается.
Код: Выделить весь код
@Echo Off
cls
	Set "BoxIn=Z:\Users"
	For /R "%BoxIn%" %%a In (.) Do (
		Echo =====
		Echo 00000 %%a

		Set "X=%%a"
		Call Echo 11111 %%X%%

		Call :Obrab "%%a" "%%X%%"
		Call Set "Y=%%X%%"
		Call Echo 66666 %%Y%%
	)		
Pause
Exit /B

:Obrab
	Echo 33333 %~1
	Echo 44444 %~2
	Call Echo 55555 %%X%%
Exit /B
Фрагмент результата у меня.
=====
00000 Z:\Users\1\Temp\MS-DOS_Flash\!!!MS-DOS-ver.5-7 (ms-dos.biz)!!!\Soft_Out\.
11111 Z:\Users\1\Temp\MS-DOS_Flash\!!!MS-DOS-ver.5-7 (ms-dos.biz)!!!\Soft_Out\.
33333 Z:\Users\1\Temp\MS-DOS_Flash\!!!MS-DOS-ver.5-7 (ms-dos.biz)!!!\Soft_Out\.
44444 Z:\Users\1\Temp\MS-DOS_Flash\!!!MS-DOS-ver.5-7 (ms-dos.biz)!!!\Soft_Out\.
55555 Z:\Users\1\Temp\MS-DOS_Flash\!!!MS-DOS-ver.5-7 (ms-dos.biz)!!!\Soft_Out\.
66666 Z:\Users\1\Temp\MS-DOS_Flash\!!!MS-DOS-ver.5-7 (ms-dos.biz)!!!\Soft_Out\.
=====
00000 Z:\Users\1\Temp\MS-DOS_Flash\!!!MS-DOS-ver.5-7 (ms-dos.biz)!!!\Я-Архив\.
11111 Z:\Users\1\Temp\MS-DOS_Flash\!!!MS-DOS-ver.5-7 (ms-dos.biz)!!!\Я-Архив\.
33333 Z:\Users\1\Temp\MS-DOS_Flash\!!!MS-DOS-ver.5-7 (ms-dos.biz)!!!\Я-Архив\.
44444 Z:\Users\1\Temp\MS-DOS_Flash\!!!MS-DOS-ver.5-7 (ms-dos.biz)!!!\Я-Архив\.
55555 Z:\Users\1\Temp\MS-DOS_Flash\!!!MS-DOS-ver.5-7 (ms-dos.biz)!!!\Я-Архив\.
66666 Z:\Users\1\Temp\MS-DOS_Flash\!!!MS-DOS-ver.5-7 (ms-dos.biz)!!!\Я-Архив\.

-------
Даже самая сложная проблема обязательно имеет простое, лёгкое для понимания, неправильное решение. Каждое решение плодит новые проблемы.

Это сообщение посчитали полезным следующие участники:

Отправлено: 10:28, 18-11-2021 | #8


Забанен


Сообщения: 346
Благодарности: 64

Профиль | Цитировать


ChimMAG, ну вот же
Скрытый текст

Код: Выделить весь код
C:\Activators
----------------------------------------------------
=>chcp 65001
Active code page: 65001


C:\Activators
----------------------------------------------------
=>for /R %a in (\) do (set X=%a  && call :Obrab  )


C:\Activators
----------------------------------------------------
=>(set X=C:\Activators\\  && call :Obrab  )


C:\Activators
----------------------------------------------------
=>echo Моя переменная для работы: C:\Activators\\
Моя переменная для работы: C:\Activators\\


C:\Activators
----------------------------------------------------
=>exit /b


C:\Activators
----------------------------------------------------
=>(set X=C:\Activators\!!!MS-DOS-ver.5-7 (ms-dos.biz)!!!\\  && call :Obrab  )


C:\Activators
----------------------------------------------------
=>echo Моя переменная для работы: C:\Activators\!!!MS-DOS-ver.5-7 (ms-dos.biz)!!!\\
Моя переменная для работы: C:\Activators\!!!MS-DOS-ver.5-7 (ms-dos.biz)!!!\\


C:\Activators
----------------------------------------------------
=>exit /b


C:\Activators
----------------------------------------------------
=>(set X=C:\Activators\KMSAuto Net 2015 v1.4.2 Portable\\  && call :Obrab  )


C:\Activators
----------------------------------------------------
=>echo Моя переменная для работы: C:\Activators\KMSAuto Net 2015 v1.4.2 Portable\\
Моя переменная для работы: C:\Activators\KMSAuto Net 2015 v1.4.2 Portable\\


C:\Activators
----------------------------------------------------
=>exit /b

Полностью скрипт:
Скрытый текст
Код: Выделить весь код
@echo on
chcp 65001

for /R %%a in (\) do ( set X=%%a&&call :Obrab )
pause
exit


:Obrab
echo Моя переменная для работы: %X%
exit /b

Отправлено: 14:42, 18-11-2021 | #9


Новый участник


Сообщения: 6
Благодарности: 0

Профиль | Отправить PM | Цитировать


Цитата megaloman:
Поэтому, если аккуратно, то вот так разными способами и ничего не обрезается и не ломается. »
Это интересный пример, я попробую использовать его.
Вообще скрипт пробегает по всему дереву, начиная с каталога запуска и считает полную длину файлов вместе с путём и выявляет имена с более 255 символами - с такими файлами бывают проблемы. Я подправил, запустил. Отработал за несколько часов более 300 тыс файлов (по моим прикидкам по тому, что он пробегал; я думал, что гораздо медленнее будет, в реальности скорее всего за 500тыс успел) и отрубился. Добавил вывод в отдельный файл трассировку пробегаемых каталогов и счётчик просмотренного. Посмотрю что из этого получится :-)

Последний раз редактировалось ChimMAG, 18-11-2021 в 16:08. Причина: Указал на чьё отвечал


Отправлено: 16:05, 18-11-2021 | #10



Компьютерный форум OSzone.net » Программирование, базы данных и автоматизация действий » Скриптовые языки администрирования Windows » CMD/BAT - Определение и работа с некорректными именами файлов

Участник сейчас на форуме Участник сейчас на форуме Участник вне форума Участник вне форума Автор темы Автор темы Шапка темы Сообщение прикреплено

Похожие темы
Название темы Автор Информация о форуме Ответов Последнее сообщение
CMD/BAT - Операция с именами файлов rider42 Скриптовые языки администрирования Windows 26 08-12-2018 21:20
CMD/BAT - Перемещение файлов в папки с аналогичными именами londondron Скриптовые языки администрирования Windows 12 22-03-2017 15:22
CMD/BAT - Создание папок и файлов со с случайными именами. Kirstem Скриптовые языки администрирования Windows 0 26-04-2015 20:06
CMD/BAT - работа с 2 текстовыми файлами, именами файлов и всё в цикле Тишина Скриптовые языки администрирования Windows 4 15-07-2012 20:26
Проблема с русскими именами файлов iml Общий по Linux 7 25-09-2006 12:40




 
Переход