Проблема пакетного переименования при работе со специальными символами в имени файла
У меня есть несколько сотен *.mp3 файлов в c:\files. Там есть все мыслимые имена файлов, такие как
- milad.mp3 (хорошее поведение)
- эй you.mp3 (пробел в имени файла)
- systemofadown.mp3 (длинное имя файла)
- howdy (1).mp3 (скобки в имени файла)
и любая комбинация трех последних условий. Я хочу переименовать файлы в 001-test.mp3, 002-mp3, ... Не имеет значения, какой файл получит какое имя. написал командный файл, чтобы сделать переименование. Вот мой код (с добавленными номерами строк):
01 rem @echo off
02 cls
03 set _number=%1
04 lfnfor on
05
06 :F1TO10
07 IF NOT EXIST *.mp3. goto end
08 if %_number% gtr 9 goto F10TO100
09 for /f %%a IN ('dir /b *.mp3') do rename %%~na.mp3 00%_number%-test.mp4
10 set /a _number +=1
11 goto F1TO10
12
13 :F10TO100
14 IF NOT EXIST *.mp3. goto end
15 if %_number% gtr 99 goto F100TO1000
16 for /f %%a IN ('dir /b *.mp3') do rename %%~na.mp3 0%_number%-test.mp4
17 set /a _number +=1
18 goto F10TO100
19
20 :F100TO1000
21 IF NOT EXIST *.mp3. goto end
22 if %_number% gtr 999 goto end
23 for /f %%a IN ('dir /b *.mp3') do rename %%~na.mp3 %_number%-test.mp4
24 set /a _number +=1
25 goto F100TO1000
26
27 :end
28 for /f %%a IN ('dir /b *.mp4') do rename %%~na.mp4 %%~na.mp3
29 echo Done
Этот код прекрасно работает для имен файлов с хорошим поведением (т.е. без пробелов, без скобок, длиной не более 8 символов). Но если у меня есть хотя бы один файл с плохим поведением имени файла, скрипт ломается (он бесконечно зацикливается, пока я не остановлю его с помощью Ctrl-C).
Проблема, очевидно, в имени файла. Как это можно исправить? Есть идеи? Я был бы очень признателен за любую помощь.
8 ответов
Прежде всего я хотел бы поблагодарить друзей, которые предложили помощь через ответы. Но ни один не был тем, что я искал. На самом деле я пришел к безупречно работающему сценарию, используя помощь, предоставленную Spire, опубликованную в качестве ответа на этот вопрос.
Вот окончательный код: (на этот раз не нужны номера строк)
rem @echo off
cls
set _number=%1
:F1TO10
IF NOT EXIST *.mp3. goto end
if %_number% gtr 9 goto F10TO100
for /f "usebackq delims=" %%x in (`dir /b *.mp3`) do rename %%~nsx.mp3 00%_number%-test.mp9
set /a _number +=1
goto F1TO10
:F10TO100
IF NOT EXIST *.mp3. goto end
if %_number% gtr 99 goto F100TO1000
for /f "usebackq delims=" %%x in (`dir /b *.mp3`) do rename %%~nsx.mp3 0%_number%-test.mp9
set /a _number +=1
goto F10TO100
:F100TO1000
IF NOT EXIST *.mp3. goto end
if %_number% gtr 999 goto end
for /f "usebackq delims=" %%x in (`dir /b *.mp3`) do rename %%~nsx.mp3 %_number%-test.mp9
set /a _number +=1
goto F100TO1000
:end
for /f %%a IN ('dir /b *.mp9') do rename %%~na.mp9 %%~na.mp3
echo Done.
Пытаться %%~fsa.mp3
вместо %%~na.mp3
,
как указано в конце в http://www.ss64.org/viewtopic.php?id=93
или добавить кавычки к длинному имени..
Как насчет замены его на хороший простой скрипт ruby?
Dir["*.mp3"].each_with_index{ |filename,index|
File.rename filename, "Test-#{index}.mp3"
}
Вы пытались поставить кавычки вокруг имен файлов for
найденный?
rename "%%~na.mp3"
вместо rename %%~na.mp3
?
Windows Vista поддерживает массовое переименование. Просто выберите все элементы в окне проводника и нажмите F2. Введите имя файла, который вы хотите (в данном случае "тест") и нажмите Enter. Бэм, все переименованы.
Это по крайней мере нормализует это для вас. Затем вы можете написать скрипт, который помещает кавычки вокруг всего, например, "%1", "%%~na.mp3" и т. Д., И все готово.
Принципиальная проблема заключается в том, что в качестве разделителя слов используется пробел, т. Е. "Foo bar.txt" считается ДВУМЯ файлами.
Вам нужно как-то корректно экранировать аргументы для cmd.exe, поэтому вам нужно проверить документацию... К сожалению, для вас весь остальной мир продвинулся дальше и предпочитает использовать любое количество альтернативных оболочек (черт, даже bash на cygwin) или, как предложил Крис, вместо этого использовать другой язык.
Ruby, Python и Perl - хороший выбор.
Если вы не возражаете против использования файла сценария Windows, вы можете очень легко выполнить эту функцию, и, возможно, ее будет легче читать / обновлять.
var path = "c:\\files";
var io = new ActiveXObject("Scripting.FileSystemObject");
Enumerator.prototype.each = function(f, c) {
for (var i = 0; !this.atEnd(); this.moveNext()) {
if (f.call(c, this.item(), i++, this)===false) break;
}
return this;
};
function fixedLength(n) {
return (n < 100 ? "0" : "") + (n < 10 ? "0" : "") + n;
};
var results = [];
new Enumerator(io.GetFolder(path).Files).each(function(file, index) {
var oldName = file.Name, newName = fixedLength(index+1) + ".mp3";
if (/\.mp3$/i.test(oldName)) {
// mp3 extension
file.Name = newName;
results.push(newName + " <-- " + oldName);
}
});
WScript.Echo(results.join("\n"));
просто сохраните как renameMP3s.js или любой другой файл.js и дважды щелкните.
Я действительно думаю, что вы выбираете сложный путь с этим. Я часто выполняю такие операции и использую BRU для таких целей (доступно еще миллион альтернатив) - он небольшой, портативный и выполняет свою работу ужасно.
Не вижу ни одной веской причины для того, чтобы тратить время на написание для этого нового пакетного файла.