通过遍历子目录自动将WAV文件转换为MP3的批处理脚本

时间:2012-11-17 09:26:04

标签: batch-file traversal directory

编辑1

第1步: 电话会话以.WAV格式记录在特定文件夹和子文件夹中(由当前日期格式的录音软件 AUTOMATICALLY 创建,即 20121119(YYYYMMDD)。此命名约定无法更改。当前日期子文件夹会在名为 RECFILED 的文件夹中的 D Drive 中自动创建。如果录制的是今天,则文件将存储在 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(明天) )等等。

现在,问题是:

  1. 遍历最新文件夹(查看d:\ RecFileD \ YYYYMMDD)并查看文件夹中是否有可用的WAV文件。如果是,则将这些文件转换为MP3并将其存储在任何特定位置的本地服务器上名为DD.MM.YYYY的文件夹中。 (今天的日期,但格式不同)。

  2. 一旦创建了文件夹(使用DD.MM.YYYY命名约定。在特定月份(即201211)需要在S3上载相同的文件夹。一旦月份发生变化,比如12月,与12月份相关的文件将放在文件夹201212中,依此类推。

  3. 这里的问题是在本地服务器上命名约定是YYYYMMDD(没有空格,点或逗号),在S3上命名约定是DD.MM.YYYY(带点)。

  4. 原始问题

    请帮我写一个批处理文件,这样我就可以自动完成将WAV文件转换为MP3的过程,然后将它们直接上传到Amazon S3到特定的文件夹。现在这是一个手动过程。

    实际上,我们正在运行一个小型呼叫中心,所有语音呼叫都会记录并保存在名为D:的{​​{1}}驱动器中的服务器上,以及以当前日期命名的子文件夹(即,RecFileD20121117等等。默认情况下,文件以WAV格式保存。在将文件上传到Amazon S3进行存储之前,我需要将文件转换为MP3。

    要求是我需要在一天结束的特定时间每天在S3上传MP3文件。问题是如何遍历最后一个文件夹(当前日期文件夹)并转换文件。在本地服务器上,语音文件保存在20121116中,在Amazon S3上,文件将上载到文件夹中:

    • d:\RecFileD\20121117\*.wav(这是11月份);

    • \BucketName\Voice\201211\17.11.2012\*.mp3(这将是12月份)(所有日期都有31个文件夹)。

    为了自动化转换,我创建了以下批处理文件。此文件使用SOX应用程序将WAV文件转换为当前文件夹中的MP3。

    \bucketName\Voice\201212\01.12.2012\*.mp3

    要自动将文件上传到S3,我将使用S3命令行工具。

    简而言之,需要采取以下步骤:

    1. 仅遍历本地服务器上的当前日期文件夹(@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 2012111520121116等),并将WAV文件转换为MP3(使用上述脚本)

    2. 将这些MP3文件移至自动创建的名为20121117的单独文件夹中(根据当前日期)。

    3. 将文件夹上传到特定位置的Amazon S3。即,17.11.2012

2 个答案:

答案 0 :(得分:0)

你所拥有的是非常好的,你非常接近。

我正在测试的环境需要do (才能让开放的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循环结束后,它将被设置为 last 值或'latest'目录。

在下面的代码中,我单独设置dirname以避免变量扩展规则出现问题。或者,您应该可以使用:

setlocal enableextensions enabledelayedexpansion 

set dirname=%%d
set year=!dirname:~0,4!

如上所述,您的问题不需要递归。我的代码只迭代每个目录,然后迭代每个文件。如果文件布局的结构较少,则表明可能需要递归。

您没有指定使用哪个Windows S3命令行工具,因此我使用本地完整路径和部分路径回显*S3COPY*。您应该可以使用复制命令替换它。

你需要从d:\RecFileD运行它,或者你可以在bat文件的顶部附近添加它:

d:
cd \RecFileD

您可能需要将s3root更改为本地S3副本的实际根目录。我没有移动文件,而是在正确的位置创建它们。

我在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 - 最新目录中的新文件,基于文件名(默认)
  • 最新 - 最新目录中的所有文件,基于文件名
  • 今天 - 今天的目录
  • newdirs - S3树中不存在的所有目录(缺少日期)
  • newfiles - S3树中不存在的所有文件
  • 所有 - 所有文件(用于覆盖S3树中的损坏)

如果过滤器为newdirsnewfilesall,则可以使用第二个参数进一步过滤目录名称。你可以使用*和?用于匹配一组文件的通配符。

如果您将脚本保存为ProcDirs.bat,则以下是一些示例:

ProcDirs all 20121119
将强制处理(或重新处理)指定的目录。

ProcDirs newdirs 201211??
将处理与目录名称匹配的新目录(从输出树中丢失)(指定年份和月份的任何一天)。

ProcDirs newfiles 2012????
将在与目录名称匹配的目录中处理新文件(从输出树中丢失)(指定年份的任何一天)。

ProcDirs
ProcDirs newlatest
完全相同,因为newlatest是默认值。这将处理(词法)'最新'目录中的新文件

代码更复杂,但太糟糕。我确实尝试使用@ Aacini的代码来获取今天的月/日/年,但它在我的系统上不起作用(因为我的日期格式必须与要求不同)。所以我使用的是一种不依赖于本地日期格式的不同方法。

我的第一个解决方案不需要延迟扩展,但是这个解决方案确实如此,我将其打开setlocal(适用于Win XP,但可能不是旧Windows)并使用!代替{{1用于环境变量替换。

%
祝你好运。我希望这会有所帮助。

答案 1 :(得分:0)

哇!这听起来比实际复杂得多!

@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的本地文件夹不够解释!

我希望这是你想要的......

安东尼奥