Редактировать 1
ШАГ 1: Телефонные разговоры записываются в формате .WAV в определенную папку и подпапки (созданные АВТОМАТИЧЕСКИ программой записи голоса в текущем формате даты, т. е. 20121119 (ГГГГММДД) . Это соглашение об именах нельзя изменить. Подпапки с текущей датой автоматически создаются на Диске D в папке с именем RECFILED. Например, если записи предназначены для сегодня файлы будут храниться в подпапке 20121119. Вчерашние файлы хранились в 20121118.
ШАГ 2: В конце дня эти файлы *.WAV необходимо преобразовать в формат *.MP3 и загрузить на Amazon S3. В настоящее время этот процесс является ручным. Так как существует много файлов WAV, поэтому я использую SOX для пакетного преобразования WAV в MP3. Для этой цели я создал пакетный файл (объясненный в моем исходном вопросе), чтобы этот процесс преобразования можно было автоматизировать. Этот пакетный файл преобразует WAV в MP3 и сохраняет файлы MP3 в той же папке, что и файлы WAV. Для этого мне нужно скопировать пакетный файл в папку и запустить его. Он конвертирует файлы и сохраняет их в той же папке.
ШАГ 3: После преобразования файлов. Затем на Amazon S3 в определенной корзине я должен создать новую папку с текущей датой, чтобы все эти MP3 можно было хранить там. НО формат даты здесь ДД.ММ.ГГГГ. Иерархия папок: \BucketName\Voice\201211\19.11.2012\*.MP3 (на сегодня), \BucketName\Voice\201211\20.11.2012\*.MP3 (на завтра) ) и так далее.
Теперь проблема в следующем:
Перейдите к последней папке (загляните в d:\RecFileD\ГГГГММДД) и посмотрите, есть ли в папке файлы WAV. Если да, преобразуйте эти файлы в MP3 и сохраните их в папке с именем ДД.ММ.ГГГГ на локальном сервере в любом определенном месте. (сегодняшняя дата, но в другом формате).
Однажды папка создается (с соглашением об именах ДД.ММ.ГГГГ. Те же самые папки должны быть загружены на S3 в определенном месяце (т. пойдет в папку 201212 и так далее.
Проблема здесь в том, что на локальном сервере соглашение об именах - ГГГГММДД (без пробелов, точек или запятых), а на S3 соглашение об именах - ДД.ММ.ГГГГ (с точками).
Исходный вопрос
Пожалуйста, помогите мне написать пакетный файл, чтобы я мог автоматизировать процесс преобразования файлов WAV в MP3, а затем загружать их непосредственно на Amazon S3 в определенные папки. Сейчас это ручной процесс.
На самом деле, у нас есть небольшой колл-центр, и все голосовые вызовы записываются и сохраняются на сервере на диске D: в папке с именем RecFileD и в подпапках, названных с текущей датой (например, 20121117, 20121116 и т. д.). По умолчанию файлы сохраняются в формате WAV. Мне нужно преобразовать файлы в MP3, прежде чем загружать их на Amazon S3 для хранения.
Требование состоит в том, что мне нужно ежедневно загружать файлы MP3 на S3 в определенное время в конце дня. Проблема заключается в том, как перейти к последней папке (папке с текущей датой) и преобразовать файлы. На локальном сервере голосовые файлы сохраняются в d:\RecFileD\20121117\*.wav, а на Amazon S3 файлы загружаются в папки:
Чтобы автоматизировать преобразование, я создал приведенный ниже пакетный файл. Этот файл использует приложение SOX для преобразования файлов WAV в MP3 в текущей папке.
@echo off
call :treeprocess
goto :eof
:treeprocess
for %%f in (*.wav) do
(
sox %%~nf.WAV %%~nf.mp3
sox %%~nf.WAV %%~nf-short.mp3 trim 0:30 1:00
)
for /D %%d in (*) do
(
cd %%d
call :treeprocess
cd ..
)
exit /b
Чтобы автоматизировать загрузку файлов на S3, я бы использовал инструмент командной строки S3.
Вкратце, необходимы следующие шаги:
Перейдите только к папке текущей даты (20121115, 20121116, 20121117 и т. д.) на локальном сервере и конвертируйте файлы WAV в MP3 (используя приведенный выше скрипт).
Переместите эти файлы MP3 в отдельную папку, созданную автоматически, с именем 17.11.2012 (на текущую дату).
Загрузите папку в Amazon S3 в определенное место. то есть \bucketname\voice\201211\17.11.2012.
Ответ 2 · Community
То, что у вас есть, довольно хорошо, вы довольно близки.
Среда, которую я тестировал, требовала do (, чтобы открывающая скобка находилась в той же строке, что и do. Ваше форматирование с новой строкой в середине может вызывать проблемы.
Чего вам совершенно не хватает, так это разбора имени каталога, который, как ожидается, будет ГГГГММДД. Вы можете сделать это с помощью:
set dirname=%%d
set year=%dirname:~0,4%
set month=%dirname:~4,2%
set day=%dirname:~6,2%
Как только вы это сделаете, легко создать имена файлов и пути на основе ГГГГ, ММ, ДД:
set s3path=!file_year!!file_month!\!file_day!.!file_month!.!file_year!
будет генерировать путь вида ГГГГММ\ДД.ММ.ГГГГ.
Вы можете получить "последний" каталог, используя:
for /f "tokens=1" %%a IN ('dir /b /a:d /o:n ????????') do (
set dirset=%%a
)
Примечание: это реализовано только во втором решении. Давайте разберем это:
dir /b /a:d /o:n ????????
Создает каталог в "голом" формате (просто список совпадающих файлов, по одному в строке), с каталогом атрибутов (только список каталогов), упорядочивает по имени (это значение по умолчанию в NTFS, но не в FAT, поэтому лучше указать порядок сортировки ), соответствующий ??????????, любые 8 символов (поскольку ожидается, что каталоги будут называться в формате ГГГГММДД, поэтому всегда 8 символов). Это возвращает упорядоченный список из 8-символьных имен каталогов.
for /f "tokens=1" %%a IN ('command') do echo %%a
Выполняет command и анализирует результаты построчно. Здесь будет отображен первый токен каждого результата.
for /f "tokens=1" %%a IN ('dir /b /a:d /o:n ????????') do (
set dirset=%%a
)
Собираем все вместе и видим, что dirset будет установлено для каждого подходящего имени каталога. Но после завершения цикла for для него будет установлено последнее значение или "последний" каталог.
В приведенном ниже коде я установил dirname отдельно, чтобы избежать проблем с правилами раскрытия переменных. В качестве альтернативы вы должны иметь возможность использовать:
setlocal enableextensions enabledelayedexpansion
set dirname=%%d
set year=!dirname:~0,4!
Ваша задача, как сказано, не требует рекурсии. Мой код просто повторяет каждый каталог, а затем повторяет каждый файл. Если макет файла менее структурирован, чем вы указываете, может потребоваться рекурсия.
Вы не указали, какой инструмент командной строки Windows S3 вы используете, поэтому я повторяю *S3COPY* с локальным полным и частичным путем. Вы должны быть в состоянии заменить это своей командой копирования.
Вам нужно будет запустить это из d:\RecFileD или вы можете добавить это вверху bat-файла:
d:
cd \RecFileD
Вам, вероятно, потребуется изменить s3root на фактический корневой каталог вашей локальной копии S3. Вместо того, чтобы перемещать файлы, sox создает их в правильном месте.
Я установил переменные года, месяца, дня в processfiles, потому что установка их в processdirs осложнена правилами раскрытия переменных.
Если вы делаете гораздо больше, чем это, я бы порекомендовал изучить Python. У него отличное сообщество/экосистема, с ним легко начать работу, и он бесплатен. Кроме того, вы не тратите все свое время на борьбу с языком.
Вот моя первая попытка:
@echo off
setlocal
set s3root=d:\s3\bucket\voice
call :processdirs
goto :eof
:processfiles
set year=%dirname:~0,4%
set month=%dirname:~4,2%
set day=%dirname:~6,2%
set s3path=%year%%month%\%day%.%month%.%year%
set s3dir=%s3root%\%s3path%
if not exist "%s3dir%" md "%s3dir%"
for %%f in (*.wav) do (
sox "%%~nf.WAV" "%s3dir%\%%~nf.mp3"
sox "%%~nf.WAV" "%s3dir%\%%~nf-short.mp3" trim 0:30 1:00
)
echo *S3COPY* %s3dir% %s3path%
goto :eof
:processdirs
for /D %%d in (*) do (
set dirname=%%d
cd "%%d"
call :processfiles
cd ..
)
goto :eof
Ответ @Aacini заставил меня понять, что, к сожалению, моего решения не хватает. Он не обрабатывает только сегодняшние файлы. Но меня беспокоит, что происходит, когда день пропускается.
Я добавил два параметра для управления тем, что обрабатывается. Первый параметр указывает именованный фильтр и может быть одним из следующих:
- newlatest - новые файлы в последнем каталоге на основе имени файла (по умолчанию)
- latest - все файлы в последнем каталоге, в зависимости от имени файла
- today - сегодняшний каталог.
- newdirs - все каталоги (отсутствуют даты), которые не существуют в дереве S3.
- newfiles - все файлы, которых нет в дереве S3.
- all - все файлы (используется для перезаписи повреждений в дереве S3)
Если используется фильтр newdirs, newfiles или all, то можно использовать второй параметр для дальнейшей фильтрации по имени каталога. Вы можете использовать * и ? подстановочные знаки для соответствия набору файлов.
Если вы сохраните скрипт как ProcDirs.bat, то вот несколько примеров:
ProcDirs all 20121119
Вызовет обработку (или повторную обработку) указанного каталога.
ProcDirs newdirs 201211??
Будет обрабатывать новые каталоги (отсутствующие в дереве вывода), соответствующие имени каталога (любой день указанного года и месяца).
ProcDirs newfiles 2012????
Будет обрабатывать новые файлы (отсутствующие в дереве вывода) в каталогах, соответствующих имени каталога (любой день указанного года).
ProcDirs
ProcDirs newlatest
Совершенно одинаковы, поскольку newlatest используется по умолчанию. Это будет обрабатывать новые файлы в (лексически) "последнем" каталоге.
Код сложнее, но не так уж и плохо. Я пытался использовать код @Aacini, чтобы получить текущий месяц/день/год, но он не работал в моей системе (поскольку мой формат даты должен отличаться от требуемого). Поэтому я использую другой подход, который не зависит от локальных форматов даты.
Мое первое решение не требовало отложенного расширения, но это требует, поэтому я включаю его с помощью setlocal (работает в Win XP, но, возможно, не в более старых Windows) и использую ! вместо % для подстановки переменных среды.
@echo off
setlocal enableextensions enabledelayedexpansion
set s3root=d:\s3\bucket\voice
rem Set the default filter mode
set newfilter=none
set dirsetfilter=none
set arg=%1
if "!arg!" == "" set arg=newlatest
if "!arg!" == "newdirs" (
set newfilter=newdirs
) else if "!arg!" == "newfiles" (
set newfilter=newfiles
) else if "!arg!" == "all" (
set dirsetfilter=none
set newfilter=none
) else if "!arg!" == "today" (
set dirsetfilter=today
) else if "!arg!" == "latest" (
set dirsetfilter=latest
) else if "!arg!" == "newlatest" (
set newfilter=newfiles
set dirsetfilter=latest
)
if !dirsetfilter! == today (
for /f "skip=1 tokens=1-3" %%a IN ('wmic path Win32_LocalTime Get Day^,Month^,Year /Format:table') do (
if %%a GTR 0 (
set now_day=%%a
set now_month=%%b
set now_year=%%c
)
)
set dirset=!now_year!!now_month!!now_day!
if not "%2" == "" echo Second parameter, dirset, ignored when filter is today
) else if !dirsetfilter! == latest (
rem pull out the name of the 'last' directory
for /f "tokens=1" %%a IN ('dir /b /a:d /o:n ????????') do (
set dirset=%%a
)
if not "%2" == "" echo Second parameter, dirset, ignored when filter is latest
) else if not "%2" == "" (
rem The second parameter is dirset. Wild card chars, *? allowed
rem only matched dir(s) processed
set dirset=%2
) else (
rem process all dirs that match filter
set dirset=*
)
call :processdirs
goto :eof
:processfiles
set file_year=!dirname:~0,4!
set file_month=!dirname:~4,2!
set file_day=!dirname:~6,2!
set s3path=!file_year!!file_month!\!file_day!.!file_month!.!file_year!
set s3dir=!s3root!\!s3path!
set skipdir=FALSE
if not exist "!s3dir!" (
md "!s3dir!"
) else (
if newdirs == !newfilter! set skipdir=TRUE
)
if !skipdir! == FALSE (
set havenewfiles=FALSE
for %%f in (*.wav) do (
set skipfile=FALSE
if newfiles==!newfilter! if exist "!s3dir!\%%~nf.mp3" set skipfile=TRUE
if !skipfile! == FALSE (
set havenewfiles=TRUE
echo sox "%%~nf.WAV" "!s3dir!\%%~nf.mp3"
sox "%%~nf.WAV" "!s3dir!\%%~nf.mp3"
)
set skipfile=FALSE
if newfiles == !newfilter! if exist "!s3dir!\%%~nf-short.mp3" set skipfile=TRUE
if !skipfile! == FALSE (
set havenewfiles=TRUE
echo sox "%%~nf.WAV" "!s3dir!\%%~nf-short.mp3" trim 0:30 1:00
sox "%%~nf.WAV" "!s3dir!\%%~nf-short.mp3" trim 0:30 1:00
)
)
if !havenewfiles! == TRUE (
echo *S3COPY* !s3dir! !s3path!
)
)
goto :eof
:processdirs
for /D %%d in (!dirset!) do (
echo Process Dir: %%d
set dirname=%%d
cd "%%d"
call :processfiles
cd ..
)
goto :eof
Удачи. Надеюсь, это поможет.