Компьютерный форум 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=285884)

Nun-Nun 01-08-2014 11:57 2384044

Замена маленькой буквы на заглавную в именах файлов
 
Нужен скрипт для следующей задачи: необходимо заменить в именах файлов одну или несколько маленьких букв на заглавные (имена файлов могут быть как схожими, так и разными). Расположение заменяемой буквы от начала имён у всех файлов, как правило, одинаковое, за исключением случая, когда буква (или несколько) находятся в конце. Например, либо у всех - последняя, либо у всех - первая, либо у всех - вторая и третья, либо у всех две последние и т.д.

Пример 1:

исходный вариант:

Иванов.txt
Петров.doc
Сидоров.rtf
Итомуподобных.docx


требуемый результат:

ИваноВ.txt
ПетроВ.doc
СидороВ.rtf
ИтомуподобныХ.docx


или так:

исходный вариант:

иванов.txt
петров.doc
сидоров.rtf
итомуподобных.docx


требуемый результат:

Иванов.txt
Петров.doc
Сидоров.rtf
Итомуподобных.docx


Пример 2:

исходный вариант:

Ивановам.txt
Петровод.doc
Сидоровтс.rtf
Итомуподобныхов.docx


требуемый результат:

ИвановАМ.txt
ПетровОД.doc
СидоровТС.rtf
ИтомуподобныхОВ.docx


или так:

исходный вариант:

17_амиванов.txt
14_одпетров.doc
30_тссидоров.rtf
65_овитомуподобных.docx


требуемый результат:

17_АМИванов.txt
14_ОДПетров.doc
30_ТССидоров.rtf
65_ОВИтомуподобных.docx


Пробовал это проделать средствами TC, но подобная замена возможна только для файлов с однотипными именами, для файлов с разными именами такой вариант не проходит. :(

gora 01-08-2014 16:02 2384147

Код:

@Echo Off
:: Кодировка файла Кириллица DOS (866)
SetLocal EnableDelayedExpansion
:: Путь к обрабатываемой папке
Set Folder=e:\Temp 1\3 3

:: Список замен
Set preset=а_А б_Б в_В г_Г д_Д е_Е ё_Ё ж_Ж з_З и_И й_Й к_К л_Л м_М н_Н о_О п_П р_Р с_С т_Т у_У ф_Ф х_Х ц_Ц ч_Ч ш_Ш щ_Щ ъ_Ъ ы_Ы ь_Ь э_Э ю_Ю я_Я
:: После проверки слово ECHO удалить
For /F "tokens=* delims=" %%A In ('Dir /S /B /A:-D "%folder%"') Do (
        Call :_case1 "%%~nA"
        Echo Ren "%%A" "!Result!%%~xA"
        Call :_case2 "%%~nA"
        Echo Ren "%%A" "!Result!%%~xA"
        Call :_case3 "%%~nA"
        Echo Ren "%%A" "!Result!%%~xA"
        Call :_case4 "%%~nA"
        Echo Ren "%%A" "!Result!%%~xA"
)
Pause
Exit


:_case1
:: Замена последнего символа в имени файла
Set Data=%~1
Set Char=%Data:~-1%
For %%I In (%preset%) Do For /F "tokens=1,2 delims=_" %%A In ("%%I") Do If %Char%==%%A Set Char=%%B& GoTo _next1
:_next1

Set Result=%Data:~0,-1%%Char%
GoTo :EOF

:_case2

:: Замена первого символа в имени файла
Set Data=%~1
Set Char=%Data:~0,1%
For %%I In (%preset%) Do For /F "tokens=1,2 delims=_" %%A In ("%%I") Do If %Char%==%%A Set Char=%%B& GoTo _next2
:_next2

Set Result=%Char%%Data:~1%
GoTo :EOF

:_case3

:: Замена двух последних символов в имени файла
Set Data0=%~1
Set Data=%Data0:~-2%
Set Result=
:_loop3

Set Char=%Data:~,1%
For %%I In (%preset%) Do For /F "tokens=1,2 delims=_" %%A In ("%%I") Do If %Char%==%%A Set Char=%%B& GoTo _next3
:_next3

Set Result=%Result%%Char%
Set Data=%Data:~1%
If Defined Data GoTo _loop3
Set Result=%Data0:~0,-2%%Result%
GoTo :EOF

:_case4

:: Замена трех символов в имени файла (с четвертого по шестой)
Set Data0=%~1
Set Data=%Data0:~3,3%
Set Result=
:_loop4

Set Char=%Data:~,1%
For %%I In (%preset%) Do For /F "tokens=1,2 delims=_" %%A In ("%%I") Do If %Char%==%%A Set Char=%%B& GoTo _next4
:_next4

Set Result=%Result%%Char%
Set Data=%Data:~1%
If Defined Data GoTo _loop4
Set Result=%Data0:~0,3%%Result%%Data0:~6%
GoTo :EOF


Nun-Nun 02-08-2014 13:27 2384412

gora,

Огромнейшее спасибо! Проверил - скрипт работает! Особо порадовало то, что скрипт обрабатывает и файлы во вложенных папках (правда почему-то не во всех).

Есть пара пожеланий (если, конечно, это не сложно):
1. Можно ли в скрипт добавить возможность проделать то же самое с названиями папок?
2. Насколько понял, скрипт выполняет за один раз только один из четырёх вариантов (замена либо только первой буквы, либо только последней и т.д.) и выполнение за один раз нескольких вариантов для него невозможно, например, сочетание варианта с заменой только первой буквы с вариантом замены только последней (во всяком случае, при попытке это сделать выполняется только то, что стоит за последним CALL)? Насколько сложно их скрестить?

P.S. Поэкспериментировал дальше: в Set preset сменил набор символов на латиницу (к сожалению, есть необходимость обрабатывать файлы и с такими именами), а для обработки взял первый попавшийся произвольный набор файлов (выдернул пару папок с файлами из MeGUI (на всякий случай выложил здесь). В итоге в работе скрипта обнаружилось несколько странностей: почему-то обработка прекращается, если встречается файл с именем, начинающимся с литеры "j", а также при обработке html-файлов, начинающихся на "a" и "b". :(

gora 02-08-2014 16:34 2384471

Цитата:

Цитата Nun-Nun
1. Можно ли в скрипт добавить возможность проделать то же самое с названиями папок? »

Замените часть скрипта на:
Код:

For /F "tokens=* delims=" %%A In ('Dir /S /B /A:D "%folder%"') Do (
        Call :_case1 "%%~nxA"
        Echo Ren "%%A" "!Result!"
        Call :_case2 "%%~nxA"
        Echo Ren "%%A" "!Result!"
        Call :_case3 "%%~nxA"
        Echo Ren "%%A" "!Result!"
        Call :_case4 "%%~nxA"
        Echo Ren "%%A" "!Result!"
)

Цитата:

Цитата Nun-Nun
Насколько понял, скрипт выполняет за один раз только один из четырёх вариантов (замена либо только первой буквы, либо только последней и т.д.) »

Так было в задании, любой из четырех вариантов, но только один. Для демонстрации я все 4 выполняю за один проход, но всегда с исходного варианта имени.
Цитата:

Цитата Nun-Nun
Насколько сложно их скрестить? »

Да не сложно, смысл сего не ясен... Вот пример двух последовательных преобразований, остальное по аналогии:
Код:

For /F "tokens=* delims=" %%A In ('Dir /S /B /A:D "%folder%"') Do (
        Call :_case1 "%%~nxA"
Rem        Echo Ren "%%A" "!Result!"
        Call :_case2 "!Result!"
        Echo Ren "%%A" "!Result!"
Rem        Call :_case3 "%%~nxA"
Rem        Echo Ren "%%A" "!Result!"
Rem        Call :_case4 "%%~nxA"
Rem        Echo Ren "%%A" "!Result!"

)

Цитата:

Цитата Nun-Nun
В итоге в работе скрипта обнаружилось несколько странностей: почему-то обработка прекращается, если встречается файл с именем, начинающимся с литеры "j", а также при обработке html-файлов, начинающихся на "a" и "b". »

Проверить не могу, ибо у меня нет измененного Вами скрипта и в нем могут быть ошибки. Но могу предположить следующее: В скрипте нет "защиты от дурака" и длина имен не проверяется на допустимую. Четвертый вариант, например, меняет символы с четвертого по шестой, а в Ваших примерах есть имена в три и даже в два символа!!! Что должен делать скрипт с такими именами? Я предполагал, что у Вас осмысленная задача (что следовало из примеров в первом посте) и Вы знаете на какие имена можно "натравить" скрипт, а какие нужно от него убрать.

Nun-Nun 02-08-2014 18:17 2384504

Цитата:

Цитата gora
Замените часть скрипта на: »

Попробовал - перед блоком обработки файлов добавил в скрипт приведённый Вами блок для обработки папок. Теперь обрабатываются и папки и файлы!

Цитата:

Цитата gora
Вот пример двух последовательных преобразований, остальное по аналогии: »

Заремаркировал ненужное (3 и 4 вариант) и попробовал ещё раз (первый + второй, т.е. как показано в Вашем втором посте) - не работает. Вернее, работает только та часть, что задана после второго CALL. :(
Цитата:

Цитата gora
смысл сего не ясен... »

Да всё очень просто. Из этого:

ивановас.txt
петровгв.doc
сидоровоп.rtf
итомуподобныхлв.docx
...
эмат.html

нужно получить вот это:

ИвановАС.txt
ПетровГВ.doc
СидоровОП.rtf
ИтомуподобныхЛВ.docx
...
ЭмАТ.html

Цитата:

Цитата gora
Проверить не могу, ибо у меня нет измененного Вами скрипта и в нем могут быть ошибки. »

Да ничего сильно не менял, заменил только
Код:

Set preset=а_А б_Б в_В г_Г д_Д е_Е ё_Ё ж_Ж з_З и_И й_Й к_К л_Л м_М н_Н о_О п_П р_Р с_С т_Т у_У ф_Ф х_Х ц_Ц ч_Ч ш_Ш щ_Щ ъ_Ъ ы_Ы ь_Ь э_Э ю_Ю я_Я
на
Код:

Set preset=a_A b_B c_C d_D e_E f_F g_G h_H i_I j_J k_K l_L m_M n_N o_O p_P q_Q r_R s_S t_T u_U v_V w_W x_X y_Y z_Z
Думаю, что можно было и не менять. Наверное можно было после вариантов замены кириллицы просто дописать варианты замены латиницы.
Цитата:

Цитата gora
а в Ваших примерах есть имена в три и даже в два символа!!! Что должен делать скрипт с такими именами? Я предполагал, что у Вас осмысленная задача (что следовало из примеров в первом посте) и Вы знаете на какие имена можно "натравить" скрипт, а какие нужно от него убрать. »

Здесь Вы правы, это моя оплошность - во-первых, упустил, что исходные имена могут быть не только на кириллице, но и на латинице, во-вторых, как-то сразу не пришло в голову упомянуть, что некоторые имена могут быть действительно короткими, хотя таковых в базе немного (например, Пак, Ли, Эм и т.д.).

P.S. С ранее названным непереименованием файлов на "j", "a", "b" и т.п. вопрос вроде разрешился - тоже моя оплошность, не полностью заремаркировал в команде for те части скрипта, что относились к другим вариантам. Если оставляю только какой-то один - всё работает.

Сейчас скрипт выглядит так:
Код:

@Echo off
:: Кодировка файла Кириллица DOS (866)
SetLocal EnableDelayedExpansion
:: Путь к обрабатываемой папке
Set Folder=C:\Temp\888

:: Список замен

Set preset=а_А б_Б в_В г_Г д_Д е_Е ё_Ё ж_Ж з_З и_И й_Й к_К л_Л м_М н_Н о_О п_П р_Р с_С т_Т у_У ф_Ф х_Х ц_Ц ч_Ч ш_Ш щ_Щ ъ_Ъ ы_Ы ь_Ь э_Э ю_Ю я_Я a_A b_B c_C d_D e_E f_F g_G h_H i_I j_J k_K l_L m_M n_N o_O p_P q_Q r_R s_S t_T u_U v_V w_W x_X y_Y z_Z

:: После проверки слово ECHO удалить

:: Блок обработки имён папок

For /F "tokens=* delims=" %%A In ('Dir /S /B /A:D "%folder%"') Do (
rem        Call :_case1 "%%~nxA"
rem        Echo Ren "%%A" "!Result!"
        Call :_case2 "%%~nxA"
        Ren "%%A" "!Result!"
rem        Call :_case3 "%%~nxA"
rem        Echo Ren "%%A" "!Result!"
rem        Call :_case4 "%%~nxA"
rem        Echo Ren "%%A" "!Result!"
)

:: Блок обработки имён файлов

For /F "tokens=* delims=" %%A In ('Dir /S /B /A:-D "%folder%"') Do (
rem        Call :_case1 "%%~nA"
rem        Ren "%%A" "!Result!%%~xA"
        Call :_case2 "%%~nA"
        Ren "%%A" "!Result!%%~xA"
rem        Call :_case3 "%%~nA"
rem        Echo Ren "%%A" "!Result!%%~xA"
rem        Call :_case4 "%%~nA"
rem        Echo Ren "%%A" "!Result!%%~xA"
)

Pause
Exit

:_case1
:: Замена последнего символа в имени файла
Set Data=%~1
Set Char=%Data:~-1%
For %%I In (%preset%) Do For /F "tokens=1,2 delims=_" %%A In ("%%I") Do If %Char%==%%A Set Char=%%B& GoTo _next1
:_next1
Set Result=%Data:~0,-1%%Char%
GoTo :EOF

:_case2
:: Замена первого символа в имени файла
Set Data=%~1
Set Char=%Data:~0,1%
For %%I In (%preset%) Do For /F "tokens=1,2 delims=_" %%A In ("%%I") Do If %Char%==%%A Set Char=%%B& GoTo _next2
:_next2
Set Result=%Char%%Data:~1%
GoTo :EOF

:_case3
:: Замена двух последних символов в имени файла
Set Data0=%~1
Set Data=%Data0:~-2%
Set Result=
:_loop3
Set Char=%Data:~,1%
For %%I In (%preset%) Do For /F "tokens=1,2 delims=_" %%A In ("%%I") Do If %Char%==%%A Set Char=%%B& GoTo _next3
:_next3
Set Result=%Result%%Char%
Set Data=%Data:~1%
If Defined Data GoTo _loop3
Set Result=%Data0:~0,-2%%Result%
GoTo :EOF

:_case4
:: Замена трех символов в имени файла (с четвертого по шестой)
Set Data0=%~1
Set Data=%Data0:~3,3%
Set Result=
:_loop4
Set Char=%Data:~,1%
For %%I In (%preset%) Do For /F "tokens=1,2 delims=_" %%A In ("%%I") Do If %Char%==%%A Set Char=%%B& GoTo _next4
:_next4
Set Result=%Result%%Char%
Set Data=%Data:~1%
If Defined Data GoTo _loop4
Set Result=%Data0:~0,3%%Result%%Data0:~6%
GoTo :EOF


gora 02-08-2014 18:48 2384511

Цитата:

Цитата Nun-Nun
Заремаркировал ненужное (3 и 4 вариант) и попробовал ещё раз (первый + второй, т.е. как показано в Вашем втором посте) - не работает. Вернее, работает только та часть, что задана после второго CALL. »

Думаю, Вы таки ошиблись, ибо там не только закомментированы строки, но и во вторую п\п передается результат работы первой п\п.
Код:

Call :_case2 "!Result!"
Цитата:

Цитата Nun-Nun
Наверное можно было после вариантов замены кириллицы просто дописать варианты замены латиницы. »

Можно.

Nun-Nun 02-08-2014 19:11 2384516

Цитата:

Цитата gora
Думаю, Вы таки ошиблись, ибо там не только закомментированы строки, но и во вторую п\п передается результат работы первой п\п. »

Вы правы! Это моя невнимательность (видимо старею). Исправил - работает.

registeruser1 24-01-2023 13:48 3001664

Вложений: 1
Добрый день!
Прошу помощи. Есть несколько сотен папок с песнями, но они в разном регистре на латинице. Хотелось бы привести всё в один формат - первая буква большая, остальные маленькие, в ручную очень долго.
Если не трудно помогите пож-ста. Написал сюда потому что на основе данного скрипта можно это наверное сделать если немного подправить его, самому не хватает знаний..

http://forum.oszone.net/attachment.p...1&d=1674558148

Foreigner 24-01-2023 14:12 3001666

registeruser1,

PowerShell:
Код:

Get-Childitem D:\Music -Recurse -File | Foreach-Object {

    Rename-Item $_ ($_.Name.ToLower() -replace '^.', { $_.Value.ToUpper() } )
}


registeruser1 24-01-2023 14:15 3001667

Спасибо конечно, а можно батником?

Foreigner 24-01-2023 14:19 3001668

Цитата:

Цитата registeruser1
а можно батником? »

Нет, к хорошему быстро привыкаешь, а плохое быстро забываешь.

DJ Mogarych 24-01-2023 14:37 3001669

Foreigner, папки же, там не так просто.

registeruser1 24-01-2023 14:39 3001670

Не, папки там в нормальном виде, в самих папках бардак

DJ Mogarych 24-01-2023 14:41 3001671

Надо поточнее писать тогда, кто такие "они".

registeruser1 24-01-2023 14:44 3001672

Согласен, сорри...

Foreigner 24-01-2023 14:53 3001673

Цитата:

Цитата DJ Mogarych
папки же, там не так просто. »

Я понял, что надо переименовать файлы.

registeruser1,
Кстати, в 5.1 такой вариант не сработает, для 5.1:

Код:

Get-Childitem D:\Music -Recurse -File | Foreach-Object {

    Rename-Item $_ ($_.Name.ToLower() -replace '^.', $_.Name[0].ToString().ToUpper())
}


YuS_2 24-01-2023 18:37 3001697

Да, пары функций в powershell не встроили...
Код:

# 1. Капитализация
function capitalize {
        param ([string]$str)
        $out = (get-culture).textinfo.totitlecase($str)
        return $out
}

# 2. Первая буква строки прописная
function toupperfirst {
        param ([string]$str)
        $out = $str.substring(0,1).toupper() +
        $str.substring(1,$str.length-1)
        return $out
}

$str = "одна СТРОКА - многО Слов"

capitalize $str
toupperfirst $str.tolower()

а далее вызывать из нужного места...


Время: 20:09.

Время: 20:09.
© OSzone.net 2001-