Войти

Показать полную графическую версию : [решено] Переименование каталогов


shraybikus
20-08-2018, 15:11
Добрый день!

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

В каталоге есть 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
В пакетных файлах отсутствует такое понятие, как «массив».

@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
Отсутствует, так отсутствует. Спасибо, всё получилось.

megaloman
20-08-2018, 19:04
В пакетных файлах отсутствует такое понятие, как «массив». »Так-то оно так, но Вы используете в решение аналог массива - нумеруете переменные. Вот решение с двумя эрзац-массивами. в переменные 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
Так-то оно так, но Вы используете в решение аналог массива - нумеруете переменные. Вот решение с двумя эрзац-массивами. »
С такой трактовкой — эрзац-массив — согласен. Насчёт «аналога массива» — нет, не могу согласиться: никак не аналог, просто отдельные переменные.

shraybikus
21-08-2018, 02:08
Но мне всё равно непонятно, почему значения 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
Но мне всё равно непонятно, почему значения 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. В условии у Вас:
строки из текстового файла.
В нём, к примеру, такое
(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. почему значения 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. а 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
Насчёт «аналога массива» — нет, не могу согласиться: никак не аналог, просто отдельные переменные. »
Верно, набор нумерованных переменных - не есть массив и даже не аналог массива... но, что интересно, как-то столкнулся с реализацией массивов именно на cmd... тогда ещё подумалось, вот ведь у человека насколько огромным желание должно было быть, чтобы наваять такое! Особенно, если учесть, что существуют готовые и более простые в использовании, пусть и не на cmd.
Но всё равно, это ведь имеет право на жизнь, особенно если случай с ОС "запущенный" и использование чего-то внешнего проблематично... вот, откопал таки ссылку (https://habr.com/post/75951/)

shraybikus
21-08-2018, 13:58
вот, откопал таки ссылку »
Я её видел, и даже пытался использовать без самой функции, потому что ссылка на неё лишь в конце статьи. :) Народ даже ООП на батниках мутит (http://dirk.rave.org/chap9.txt).

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

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




© OSzone.net 2001-2012