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

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

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

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


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

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


Изменения
Автор: HankHank
Дата: 27-01-2022
Привет.

Возникла задача, связанная с обработкой текстового файла.

Предыстория в следующих двух абзацах. Её можно пропустить.

Фонотека на дисках USB HDD структурирована определённым образом. В ней используются точки соединения - JUNCTION. Изначально предполагалось работать с этими дисками, монтируя тома каждый раз на букву “H:”.
Однако, спустя время, с монтированием заморачиваться поднадоело.
И для этого в файловой системе NTFS появились относительные символьные ссылки – SYMLINKD.
Процедура замены JUNCTION на SYMLINKD понятна. Для этого есть соответствующая команда NTLinks Maker http://wincmd.ru/plugring/NTLinksMaker.html .
Также понятно, как вывалить информацию обо всех JUNCTION в файл:

@chcp 1251 >nul
dir /AL /S H:\ >JtoS.txt

В итоге файл JtoS.txt содержит регулярную структуру данных. Например:

Код: Выделить весь код
 Том в устройстве H имеет метку 2 NTFS
 Серийный номер тома: CAE4-9F0A


 Содержимое папки H:\Слушать\Слушать\ Инструменты\Труба (trumpet)

09.12.2010  23:43    <JUNCTION>     Baldauf Rudiger [\??\H:\Фонотека\Jazz - fusion\Baldauf Rudiger]
29.10.2011  02:21    <JUNCTION>     Beiderbecke Leon Bix [\??\h:\Фонотека\Jazz\Beiderbecke Leon Bix]
...
               0 файлов              0 байт
...

 Содержимое папки H:\Слушать\Слушать\Modern jazz

09.10.2010  08:28    <JUNCTION>     Lloyd Charles [\??\H:\Фонотека\Jazz - avant-guard\Lloyd Charles]
               0 файлов              0 байт

 Содержимое папки H:\Слушать\Слушать\Smooth

23.08.2010  21:29    <JUNCTION>     Blake Aaron - Desire (2007) [\??\H:\Фонотека\Jazz - smooth\Aaron Blake\Blake Aaron - Desire (2007)]
02.09.2010  18:56    <JUNCTION>     Club des Belugas - Swop (2008) [\??\H:\Фонотека\Jazz - smooth\ Various\Club des Belugas - Swop (2008)]
...
               0 файлов              0 байт

     Всего файлов:
               1 файлов              0 байт
             665 папок  316*940*726*272 байт свободно
Очевидно, что вся информация, нужная для реорганизации дисков, присутствует.

Формально нужно организовать цикл по секциям, начинающимся со строк “Содержимое папки”.
В каждой секции пройти по строкам, содержащим “<JUNCTION>”, каждый раз в переменную %t помещая содержимое квадратных скобок без символов “\??\” (целевой объект), а в переменную %l – ссылку.

Для первого вхождения:
%t = “H:\Фонотека\Jazz - fusion\Baldauf Rudiger”,
%l = “H:\Слушать\Слушать\ Инструменты\Труба (trumpet)\Baldauf Rudiger”.
Для второго вхождения:
%t = “h:\Фонотека\Jazz\Beiderbecke Leon Bix”,
%l = “H:\Слушать\Слушать\ Инструменты\Труба (trumpet)\Beiderbecke Leon Bix”.
и т.д.

%t лежит внутри “[\??\ ... ]”.
%l образуется конкатенацией строки, стоящей следом за “Содержимое папки” , бэк-слеша и строки, стоящей между “<JUNCTION>” и строкой ”[\??\“ без лидирующих и замыкающих пробелов.

В именах файлов, кроме русских букв, могут встречаться спецсимволы (,;:_ и т.п.).

Помогите, плиз, с шаблоном обработки.
Саму процедуру замены с удалением JUNCTION и созданием SYMLINKD вставлю в шаблон самостоятельно.

Спасибо заранее.

Отправлено: 11:16, 27-01-2022

 

Ветеран


Contributor


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

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


Не думаю, что эта задача может быть надежно реализована в CMD из-за спецсимволов. Попробуйте формальное решение:
Код: Выделить весь код
@Echo Off
cls
>nul Chcp  1251
	Set "FileIn=Z:\Box_In\JtoS.txt"

	FOR /F "usebackq delims=" %%s In ("%FileIn%") DO (
		FOR /F "usebackq tokens=3* delims= " %%a In (`Echo "%%s"^|Find /I "Содержимое папки"`) DO (
			Set "Fold=%%~b"
			Call Set "Fold=%%Fold:~0,-1%%"
		)
		FOR /F "usebackq tokens=3* delims= " %%a In (`Echo "%%s"^|Find /I "<JUNCTION>"`) DO (
			Call Set "Junk=%%Fold%%\%%~b"
			Call Set "Junk=%%Junk:~0,-1%%"
			Call Set "Junk=%%Junk: [\??\=[%%"
			FOR /F "usebackq tokens=1,2 delims=[]" %%i In (`Call Echo %%Junk%%`) DO (
rem				Set "L=%%i"
rem				Set "T=%%j"
rem				Call Echo "%%T%%"  &Call Echo "%%L%%"
				Call :Rezult "%%j" "%%i"
			)
		)
	)
pause
Exit /B

:Rezult
	Echo %1
	Echo %2
Exit /B
Наверное, удобнее выделенными строками пользоваться внутри процедуры. Я заремил использование переменных в Echo внутри цикла - имхо, это не удобно

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


Последний раз редактировалось megaloman, 27-01-2022 в 18:32.

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

Отправлено: 16:57, 27-01-2022 | #2



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

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


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

fascinating rhythm


Moderator


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

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


Powershell:

Код: Выделить весь код
$strNum = ((gc "D:\temp\JtoS.txt" -OutVariable txt |sls 'Содержимое папки').LineNumber|% {$_ - 1})
$strNum += $txt.count
$c = 0

$report = @()
$strNum |% {
$start = $strNum[$c]
$end = $strNum[$c+1] - 1; if ($end -eq -1) {$end = $txt.count}
$piece = ($txt)[$start..$end]
    ($piece) -match '<junction>' |% {
        $obj = [pscustomobject]@{
        t = $_ -replace '.*\\\?\?\\' -replace '\]'
        l = (($piece) -match 'Содержимое папки' -replace '.*папки').trim() + '\' + `
        ($_ -replace '.*<junction>\s+' -replace '\s+\[.*').trim()
        }
    $report += $obj
    }
$c = $c+1
}
Код: Выделить весь код
$report

t                                                                 l                                                                   
-                                                                 -                                                                   
H:\Фонотека\Jazz - fusion\Baldauf Rudiger                         H:\Слушать\Слушать\ Инструменты\Труба (trumpet)\Baldauf Rudiger     
h:\Фонотека\Jazz\Beiderbecke Leon Bix                             H:\Слушать\Слушать\ Инструменты\Труба (trumpet)\Beiderbecke Leon Bix
H:\Фонотека\Jazz - avant-guard\Lloyd Charles                      H:\Слушать\Слушать\Modern jazz\Lloyd Charles                        
H:\Фонотека\Jazz - smooth\Aaron Blake\Blake Aaron - Desire (2007) H:\Слушать\Слушать\Smooth\Blake Aaron - Desire (2007)               
H:\Фонотека\Jazz - smooth\ Various\Club des Belugas - Swop (2008) H:\Слушать\Слушать\Smooth\Club des Belugas - Swop (2008)
Бикс Бейдербек - такое сейчас редко увидишь в фонотеке...

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

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

Отправлено: 17:41, 27-01-2022 | #3


Ветеран


Contributor


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

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


HankHank, Не думаю, что хорошая идея копаться в файле. А почему бы сразу не обрабатывать вывод Dir?
Код: Выделить весь код
@Echo Off
cls
>nul Chcp  1251
	Set "BoxIn=H:\"
	
	FOR /F "usebackq delims=" %%d In (`2^>nul Dir "%BoxIn%" /AL /S /B`) DO (
		FOR /F "usebackq tokens=1,2 delims=[]" %%i In (`2^>nul Dir /AL "%BoxIn%%%~nxd*.*"^|Find /I "<JUNCTION>"`) DO (
			Echo.
		        Echo "%%d"
			Set "L=%%j"
			Call Set "L=%%L:\??\=%%"
			Call Echo "%%L%%"
		)
	)
pause
Exit /B
Полноценно не тестировал,

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


Последний раз редактировалось megaloman, 27-01-2022 в 18:38.

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

Отправлено: 18:29, 27-01-2022 | #4


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


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

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


Код для скрипта может быть проще, если использовать команду

DIR /AL /B /S H:\

Тогда получим чистые строки с полными путями к ссылкам:

Код: Выделить весь код
H:\Слушать\Слушать\Albright Gerald
H:\Слушать\Слушать\Alex Rostotsky - Time when fish think of the past (2004)
H:\Слушать\Слушать\Dave Brubeck - Ken Burns Jazz (Columbia - Legacy Records) 2000
H:\Слушать\Слушать\Dino Saluzzi - El Encuentro (2010) [Flac]
H:\Слушать\Слушать\Modern Jazz Quartet - Live At The Lighthouse (MFSL MFCD 827) (1967)
…
А, еcли вызвать по ссылке FSUTIL, то получим список строк, в котором нас интересует “Print Name:” - это и будет целевой объект.

Например:

FSUTIL reparsepoint query “H:\Слушать\Слушать\Alex Rostotsky - Time when fish think of the past (2004)”

Код: Выделить весь код
Reparse Tag Value : 0xa0000003
Tag value: Microsoft
Tag value: Name Surrogate
Tag value: Mount Point
Substitue Name offset: 0
Substitue Name length: 184
Print Name offset:     186
Print Name Length:     176
Substitute Name:       \??\h:\Фонотека\Jazz\Rostotsky Alex\Alex Rostotsky - Time when fish think of the past (2004)
Print Name:            h:\Фонотека\Jazz\Rostotsky Alex\Alex Rostotsky - Time when fish think of the past (2004)
…
Таким образом, проблемы со спецсимволами серьёзно сокращаются.

Мне кажется, при таком раскладе шаблон для CMD вполне должен прокатить.

Отправлено: 21:05, 27-01-2022 | #5


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


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

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


Цитата megaloman:
Не думаю, что хорошая идея копаться в файле. А почему бы сразу не обрабатывать вывод Dir? »
Идея хорошая по причине того, что вывести простыню со всеми файлами можно всего один раз.
После чего брать из файла мелкие порции и отладить скрипт. Засада ожидается с русскими символами и спецсимволами.
А уже большими частями обработать всё оставшееся безобразие.

Отправлено: 10:13, 28-01-2022 | #6


Ветеран


Contributor


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

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


Цитата HankHank:
Идея хорошая по причине того, что вывести простыню со всеми файлами можно всего один раз.
После чего брать из файла мелкие порции и отладить скрипт. »
Тут уж в огороде бузина а в Киеве дядька: отлаживаем скрипт, который удобно отлаживать, а эффективно использовать будем другой, неотлаженный.
Берите скрипт с непосредственной обработкой Dir и натравливайте его на небольшую папку.

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

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

Отправлено: 10:33, 28-01-2022 | #7


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


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

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


Цитата megaloman:
Берите скрипт с непосредственной обработкой Dir и натравливайте его на небольшую папку »
Тоже вариант.
Только обходить вручную весь диск - не лучшая идея.
Плоская "простыня" кажется удобнее.

Отправлено: 10:44, 28-01-2022 | #8


Ветеран


Contributor


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

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


Цитата HankHank:
Только обходить вручную весь диск - не лучшая идея. »
Не обходите. Укажите, для отладки, для Dir папочку, например в моём варианте:

Set "BoxIn=H:\Слушать\Слушать\Modern jazz\"
или более обьемную:
Set "BoxIn=H:\Слушать\Слушать\"

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

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

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

Отправлено: 11:17, 28-01-2022 | #9


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


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

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


У меня начальные познания о командных файлах. Но CALL-оператор, вроде, вызывает внешний комфайл или передаёт управление внутри того же файла.
Подскажите, в чём фишка употребления CALL в сочетании с другими операторами типа:
Цитата megaloman:
Call Set "Junk=%%Junk:~0,-1%%"
Call Echo "%%T%%" &Call Echo "%%L%%" »
?

Отправлено: 15:25, 28-01-2022 | #10



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

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

Похожие темы
Название темы Автор Информация о форуме Ответов Последнее сообщение
CMD/BAT - Записать название файла в начало текстового файла krambrige Скриптовые языки администрирования Windows 3 15-12-2018 17:23
CMD/BAT - [решено] Обработка получаемых переменных из текстового файла alexxx2011 Скриптовые языки администрирования Windows 2 14-12-2017 15:54
Любой язык - Записать информацию о пользователях в AD из текстового файла. dasgespenst Скриптовые языки администрирования Windows 2 29-07-2014 09:53
CMD/BAT - [решено] Выделить из текстового файла строки, содеражщие дату формата DD.MM.YYYY за указанный jrd Скриптовые языки администрирования Windows 2 17-02-2012 16:57
Неправильно отображаются данные при вводе их из текстового файла! Sox Программирование и базы данных 3 08-03-2006 17:23




 
Переход