То, что у вас есть, довольно хорошо, вы довольно близки.
Среда, которую я тестировал, требовала 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
Удачи. Надеюсь, это поможет.
person
Community
schedule
17.11.2012