![](/img/trans.png)
[英]Batch convert .wav files to .mp3 files through sub-directories then delete the remaining .wav files
[英]Batch Script for conversion of WAV files to MP3 automatically by traversing through sub-directories
步骤1:电话交谈以.WAV格式记录在特定的文件夹和子文件夹中(由语音记录软件自动创建,当前日期格式为20121119(YYYYMMDD) 。此命名约定无法更改。子文件夹是在D驱动器的RECFILED文件夹中自动创建的, 例如 ,如果今天录制的文件将存储在20121119子文件夹中,而昨天的文件存储在20121118中 。
步骤2:最终,这些* .WAV文件需要转换为* .MP3格式并上传到Amazon S3。 目前,此过程是手动的。 既然有很多WAV文件,所以我使用SOX将WAV批量转换为MP3。 为此,我创建了一个批处理文件(在原始问题中进行了解释),以便可以自动执行此转换过程。 此批处理文件将WAV转换为MP3,并将MP3文件与WAV文件保存在同一文件夹中。 为此,我要做的是将批处理文件复制到文件夹中并运行它。 它将转换文件并将其保存在同一文件夹中。
步骤3:文件转换后。 然后在Amazon S3的特定存储桶中,我必须创建一个具有当前日期的新文件夹,以便所有这些MP3都可以存储在该文件夹中。 但是,此处的日期格式为DD.MM.YYYY 。 文件夹层次结构为\\ BucketName \\ Voice \\ 201211 \\ 19.11.2012 \\ *。MP3(适用于今天) , \\ BucketName \\ Voice \\ 201211 \\ 20.11.2012 \\ *。MP3(适用于明天)等。
现在,问题是:
遍历到最新文件夹(查看d:\\ RecFileD \\ YYYYMMDD),然后查看该文件夹中是否有WAV文件。 如果是,请将这些文件转换为MP3并将其存储在任何特定位置的本地服务器上名为DD.MM.YYYY的文件夹中。 (今天的日期,但格式不同)。
一次,创建文件夹(使用DD.MM.YYYY命名约定。同一文件夹需要在特定月份(即201211)上上传到S3。一旦月份更改(例如12月),则与12月份有关的文件将放在文件夹201212中,依此类推。
这里的问题是,在本地服务器上,命名约定为YYYYMMDD(不带空格,点或逗号),在S3上,命名约定为DD.MM.YYYY(带点)。
请帮我写一个批处理文件,以便我可以自动将WAV文件转换为MP3,然后将它们直接上传到Amazon S3到特定文件夹。 现在这是一个手动过程。
事实上,我们正在运行一个小型呼叫中心,所有的语音通话记录和保存在服务器上的D:
推动命名的文件夹RecFileD
,并用当前日期命名的子文件夹(例如, 20121117
, 20121116
等)。 默认情况下,文件以WAV格式保存。 我需要先将文件转换为MP3,然后再将其上传到Amazon S3进行存储。
要求是我需要在一天的特定时间每天在S3上载MP3文件。 问题是如何遍历最后一个文件夹(当前日期文件夹)并转换文件。 在本地服务器上,语音文件保存在d:\\RecFileD\\20121117\\*.wav
,在Amazon S3上,这些文件上传到以下文件夹中:
\\BucketName\\Voice\\201211\\17.11.2012\\*.mp3
(用于11月);
\\bucketName\\Voice\\201212\\01.12.2012\\*.mp3
(适用于12月)( \\bucketName\\Voice\\201212\\01.12.2012\\*.mp3
31个文件夹)。
为了自动进行转换,我创建了以下批处理文件。 该文件使用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
。
您所拥有的非常好,您也非常接近。
我在必需的do (
上测试的环境do (
将open paren与do放在同一行。中间用换行符进行格式化可能会导致问题。
您完全缺少的是对目录名称的任何解析,该解析应该是YYYYMMDD。 您可以执行以下操作:
set dirname=%%d
set year=%dirname:~0,4%
set month=%dirname:~4,2%
set day=%dirname:~6,2%
完成此操作后,可以轻松地基于YYYY,MM和DD创建文件名和路径:
set s3path=!file_year!!file_month!\!file_day!.!file_month!.!file_year!
将生成类似YYYYMM \\ DD.MM.YYYY的路径。
您可以使用以下命令获取“ last”目录:
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个字符(因为目录的命名方式应为YYYYMMDD,因此始终为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*
。 您应该可以使用copy命令替换它。
您需要从d:\\RecFileD
运行此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的答案使我意识到,不幸的是我缺乏解决方案。 它不只处理今天的文件。 但是我担心跳过一天会发生什么。
我添加了两个参数来控制要处理的内容。 第一个参数指定一个命名过滤器,可以是以下其中一个:
如果过滤器是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
祝好运。 我希望这有帮助。
哇! 听起来比实际要复杂得多!
@echo off
rem Create folder names from current date, MM/DD/YYYY locale format is assumed
for /F "tokens=1-3 delims=/" %%a in ("%date%") do (
set YYYYMMDD=%%c%%a%%b
set YYYYMM=%%c%%a
set DD.MM.YYYY=%%b.%%a.%%c
)
rem Enter into target folder
cd /D D:\RecFileD\%YYYYMMDD%
rem Convert WAV files to MP3 using SOX
for %%f in (*.wav) do (
sox %%~nf.WAV %%~nf.mp3
sox %%~nf.WAV %%~nf-short.mp3 trim 0:30 1:00
)
rem Move MP3 files to brother folder
md ..\%DD.MM.YYYY%
move *.mp3 ..\%DD.MM.YYYY%
rem Upload the folder to Amazon S3
echo S3COPY from ..\%DD.MM.YYYY% to \bucketname\voice\%YYYYMM%\%DD.MM.YYYY%
我建议您在描述问题时尽可能简洁,但不要忘记任何细节。 例如,在您的(长篇)描述中,对名为17.11.2012
的本地文件夹的解释还不够!
我希望这就是你想要的...
安东尼奥
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.