Компьютерный форум OSzone.net  

Компьютерный форум OSzone.net (http://forum.oszone.net/index.php)
-   Скриптовые языки администрирования Windows (http://forum.oszone.net/forumdisplay.php?f=102)
-   -   [решено] Переименование каталогов (http://forum.oszone.net/showthread.php?t=336300)

shraybikus 20-08-2018 15:11 2827548

Переименование каталогов
 
Добрый день!

Помогите, пожалуйста, реализовать следующее:

В каталоге есть 10 подкаталогов типа: 100_0447, 100_0448 и пр. Нужно переименовать их, дописав в конец строки из текстового файла.

В нём, к примеру, такое
(1000)
(750)
(600)
(500)
(400)
(300)
(200)
(100)
(50)
(25)

Подкаталоги должны переименоваться так: 100_0447 (1000), 100_0448 (750) и т.д.

Пробовал так:

echo off
setlocal ENABLEEXTENSIONS
setlocal ENABLEDELAYEDEXPANSION
dir /B /A:D >dir.txt

For %%a In (1000 750 600 500 400 300 200 100 50 25) Do (Set /a cnt +=1& Set Arr[!cnt!]=%%a
)
for /f "usebackq delims=" %%i in ("dir.txt") do (Set /a index +=1
echo i= %%i
echo index= !index!
echo !Arr[%%index]!
echo !Arr[1]! !Arr[2]! !Arr[3]! !Arr[4]! !Arr[5]! !Arr[5]! !Arr[7]! !Arr[8]! !Arr[9]! !Arr[10]!
)
pause

Но почему-то, в цикле не выводятся элементы массива, хотя они определены:
Скрытый текст
b:\test>echo off
i= 100_0447
index= 1
Режим вывода команд на экран (ECHO) отключен.
1000 750 600 500 400 400 200 100 50 25
i= 100_0448
index= 2
Режим вывода команд на экран (ECHO) отключен.
1000 750 600 500 400 400 200 100 50 25
i= 100_0449
index= 3
Режим вывода команд на экран (ECHO) отключен.
1000 750 600 500 400 400 200 100 50 25
i= 100_0450
index= 4
Режим вывода команд на экран (ECHO) отключен.
1000 750 600 500 400 400 200 100 50 25
i= 100_0451
index= 5
Режим вывода команд на экран (ECHO) отключен.
1000 750 600 500 400 400 200 100 50 25
i= 100_0452
index= 6
Режим вывода команд на экран (ECHO) отключен.
1000 750 600 500 400 400 200 100 50 25
i= 100_0453
index= 7
Режим вывода команд на экран (ECHO) отключен.
1000 750 600 500 400 400 200 100 50 25
i= 100_0454
index= 8
Режим вывода команд на экран (ECHO) отключен.
1000 750 600 500 400 400 200 100 50 25
i= 100_0455
index= 9
Режим вывода команд на экран (ECHO) отключен.
1000 750 600 500 400 400 200 100 50 25
i= 100_0456
index= 10
Режим вывода команд на экран (ECHO) отключен.
1000 750 600 500 400 400 200 100 50 25
Для продолжения нажмите любую клавишу . . .

Iska 20-08-2018 16:24 2827569

В пакетных файлах отсутствует такое понятие, как «массив».

Код:

@echo off
setlocal enableextensions enabledelayedexpansion

set sSourceFolder=C:\Мои проекты\0186
set sNamesFileList=C:\Мои проекты\0186\Names.txt

if exist "%sSourceFolder%\." (
        if exist "%sNamesFileList%" (
                set /a iCount = 0
               
                for /f "usebackq delims=" %%i in ("%sNamesFileList%") do (
                        set sNameFileList!iCount!=%%~i
                        set /a iCount += 1
                )
               
                set /a iCount = 0
               
                for /f "usebackq delims=" %%i in (
                        `2^>nul dir /b /a:d "%sSourceFolder%\*.*"`
                ) do (
                        if defined sNameFileList!iCount! call ren "%sSourceFolder%\%%~i" "%%~i %%sNameFileList!iCount!%%"
                        set /a iCount += 1
                )
        ) else (
                echo Can't find name's file list file [%sNamesFileList%].
                exit /b 2
        )
) else (
        echo Can't find source folder [%sSourceFolder%].
        exit /b 1
)

endlocal
exit /b 0


shraybikus 20-08-2018 16:39 2827572

Отсутствует, так отсутствует. Спасибо, всё получилось.

megaloman 20-08-2018 19:04 2827598

Цитата:

Цитата Iska
В пакетных файлах отсутствует такое понятие, как «массив». »

Так-то оно так, но Вы используете в решение аналог массива - нумеруете переменные. Вот решение с двумя эрзац-массивами. в переменные A1...A10 занесем значения 1000 ... 25, а в переменные B1... занесём имена исходных папок для переименования.
Код:

@Echo Off
        Set "Txt=1000 750 600 "500" 400 300 200 100 50 25"

        Set "BoxIn=Z:\Soft_In"
        Set "Mask=100_*.*"

        Set /A i=0
        FOR %%f IN (%Txt%) Do Call :MassIn "A" "i" %%f

        Set /A j=0
        FOR /D %%f IN ("%BoxIn%\%Mask%") DO  Call :MassIn "B" "j" "%%f"
       
        If %i% GTR %j% Set /A i=%j%
        If Not %i% EQU 0 FOR /L %%f IN (1,1,%i%) DO Call :MassRen "%%A%%f%%" "%%B%%f%%"
GoTo :Eof

:MassIn
        Set /A %~2+=1
        Call Set /A @i=%~2
        Set "%~1%@i%=%~3"
GoTo :Eof

:MassRen
        Ren %2 "%~nx2 (%~1)"
GoTo :Eof

Я не стал считывать номера из текстового файла - для моего решения это не принципиально. Хотя не проблема: Можно эти номера аналогичным путём занести в эрзац-массив из текстового файла.

Iska 20-08-2018 19:31 2827607

Цитата:

Цитата megaloman
Так-то оно так, но Вы используете в решение аналог массива - нумеруете переменные. Вот решение с двумя эрзац-массивами. »

С такой трактовкой — эрзац-массив — согласен. Насчёт «аналога массива» — нет, не могу согласиться: никак не аналог, просто отдельные переменные.

shraybikus 21-08-2018 02:08 2827646

Но мне всё равно непонятно, почему значения echo !Arr[1]! !Arr[2]! !Arr[3]! !Arr[4]! !Arr[5]! !Arr[5]! !Arr[7]! !Arr[8]! !Arr[9]! !Arr[10]! выводятся, а echo !Arr[%%index]! - нет.
Может я неправильно передаю индекс? С этими процентами, восклицательными знаками и пр. - постоянная путаница. :(

Iska 21-08-2018 08:09 2827658

Цитата:

Цитата shraybikus
Но мне всё равно непонятно, почему значения echo !Arr[1]! !Arr[2]! !Arr[3]! !Arr[4]! !Arr[5]! !Arr[5]! !Arr[7]! !Arr[8]! !Arr[9]! !Arr[10]! выводятся, а echo !Arr[%%index]! - нет. »

Ну, давайте начнём.

1.
Код:

setlocal enableextensions
setlocal enabledelayedexpansion

— технически допустимо, но логически неверно. Таким образом Вы задаёте сначала один локальный контекст, затем, тут же, ещё один. В этом нет смысла. Правильным будет использование одной команды setlocal:
Код:

setlocal enableextensions enabledelayedexpansion
2. В условии у Вас:
Цитата:

Цитата shraybikus
строки из текстового файла.
В нём, к примеру, такое
(1000)
(750)
(600)
(500)
(400)
(300)
(200)
(100)
(50)
(25) »

а в коде эти строки напрямую заданы строкой:
Код:

For %%a In (1000 750 600 500 400 300 200 100 50 25) Do (Set /a cnt +=1& Set Arr[!cnt!]=%%a)
Для читабельности лучше не стесняться использовать фолдинг, наподобие:
Код:

for %%i in (1000 750 600 500 400 300 200 100 50 25) do (
        set /a cnt += 1
        set Arr[!cnt!]=%%i
)

3.
Цитата:

Цитата shraybikus
почему значения echo !Arr[1]! !Arr[2]! !Arr[3]! !Arr[4]! !Arr[5]! !Arr[5]! !Arr[7]! !Arr[8]! !Arr[9]! !Arr[10]! выводятся »

Потому что переменные окружения !Arr[1]! и т.д. определены и корректно раскрываются в свои значения. Причём здесь нет никакой необходимости использовать отложенное раскрытие, достаточно простого:
Код:

echo %Arr[1]% %Arr[2]% %Arr[3]% %Arr[4]% %Arr[5]% %Arr[5]% %Arr[7]% %Arr[8]% %Arr[9]% %Arr[10]%
4.
Цитата:

Цитата shraybikus
а echo !Arr[%%index]! - нет. »

Потому что непонятно, что Вы хотите сделать. У нас определена переменная окружения index, у нас определена переменная цикла разбора i.

Первую можно получить по !index! [или call %%index%%] (вот здесь отложенное раскрытие [или двойное обычное раскрытие] уже нужно, потому что её значение ранее задаётся внутри тех же операторных скобок). Вторая доступна по %%i. А что у нас?

А у нас так:
Код:

echo !Arr[%%index]!
Вы думаете, что %%index — переменная окружения index? Это не так. В этом коде нет переменной окружения index. Зато есть переменная цикла разбора %%i. Которая раскроется в своё значение из содержимого файла dir.txt — сначала в 100_0447, затем в 100_0448 и т.д. Таким образом, интерпретатор команд при попытке отложенного раскрытия сначала увидит переменную окружения Arr[100_0447ndex], которая, разумеется, не существует, затем переменную окружения Arr[100_0448ndex], которая тоже не существует, и т.д.

Как это можно обойти? Например, так, как в моём коде выше:
Код:

if defined sNameFileList!iCount! call ren "%sSourceFolder%\%%~i" "%%~i %%sNameFileList!iCount!%%"
Для Вашего кода это может выглядеть как:
Код:

call echo %%Arr[!index!]%%

YuS_2 21-08-2018 13:35 2827730

Цитата:

Цитата Iska
Насчёт «аналога массива» — нет, не могу согласиться: никак не аналог, просто отдельные переменные. »

Верно, набор нумерованных переменных - не есть массив и даже не аналог массива... но, что интересно, как-то столкнулся с реализацией массивов именно на cmd... тогда ещё подумалось, вот ведь у человека насколько огромным желание должно было быть, чтобы наваять такое! Особенно, если учесть, что существуют готовые и более простые в использовании, пусть и не на cmd.
Но всё равно, это ведь имеет право на жизнь, особенно если случай с ОС "запущенный" и использование чего-то внешнего проблематично... вот, откопал таки ссылку

shraybikus 21-08-2018 13:58 2827732

Цитата:

Цитата YuS_2
вот, откопал таки ссылку »

Я её видел, и даже пытался использовать без самой функции, потому что ссылка на неё лишь в конце статьи. :) Народ даже ООП на батниках мутит.

Iska 21-08-2018 14:30 2827741

Цитата:

Цитата YuS_2
вот, откопал таки ссылку »

Дело в том, что это не массив. В принципе. Не массив, и всё тут. Потому как любая реализация подобного эрзац-массива будет обставлена таким количеством оговорок и ограничений (чего только стоит отдельная переменная окружения для хранения размера массива), что нет смысла как-то сим заморачиваться.

Ну, и в скобках отмечу, что:
Цитата:

Надо сказать пару слов о процедурах, возвращающих значение. Т.к. в батниках нет возможности вернуть значение из процедуры (будем так называть то, что вызывается через call),
— неверно. Есть возможность :).


Время: 19:50.

Время: 19:50.
© OSzone.net 2001-