【问题标题】:Bash script convert into batchBash脚本转换成批处理
【发布时间】:2020-06-28 18:09:26
【问题描述】:

我用 bash 写了一个脚本。该脚本正在制作一个扩展名为 .DAT 的文件,该文件从 mp3 文件中获取详细信息。我使用 exiftool 来获取 id3 标签。 我有一个名为 Miley Cyrus - Wrecking Ball.mp3 的 mp3 文件,这个脚本制作文件 Miley Cyrus - Wrecking Ball.DAT,其中包含一些来自 ID3 标签的详细信息。

我在 bash 中的脚本。

#!/bin/bash 
find . -name '*.mp3' -print0 | while read -d $'\0' file
do

ARTIST=$(exiftool -p '$Artist' "$file")
ALBUM=$(exiftool -p  '$Album' "$file")
TITLE=$(exiftool -p '$Title'  "$file")

touch "$file".DAT

echo "Lit=" >> "$file".DAT
echo "ENG=" >> "$file".DAT
echo "CRD=" >> "$file".DAT
echo "TIT=$TITLE" >> "$file".DAT
echo "ALB=$ALBUM" >> "$file".DAT
echo "ART=$ARTIST" >> "$file".DAT

done

我需要那个脚本,但在 Windows 中,这开始了我的麻烦。我不知道我可以从哪种方式开始。我必须使用哪些选项 for 循环,为什么 exiftool 没有从文件中获取标签?我尝试使用 fname 来分隔名称和扩展名,但没有结果。

  1. 我需要做什么才能开始在 Windows 中使用此脚本。
@echo off 

setlocal enableDelayedExpansion 

for %%a in (*.mp3) do (

 set "Title=(exiftool -p Title '%%a')"
 set "Album=(exiftool -p Album '%%a')"
 set "Artist=(exiftool -p Artist '%%a')"


echo "Lit=" >> "%%a".DAT
echo "ENG=" >> "%%a".DAT
echo "CRD=" >> "%%a".DAT
echo "Title=%Title% >> "%%a".DAT
echo "Album=%Album% >> "%%a".DAT
echo "Artist=%Artist% >> "%%a".DAT
)

exiftool 在 windows 文件夹中。

【问题讨论】:

  • “.DAT”文件是否总是附加到,还是每次都是新的?
  • 欢迎来到 SO,@Remik。这个问题相当广泛。 SO 倾向于一次只关注一 (1) 个问题。解决此问题的一种方法是将其编写为 pwsh 脚本。这将允许在 Linux、Mac、Windows 等上运行相同的代码。github.com/PowerShell/PowerShell
  • 对于文件夹中的每个 mp3 都应该是新的,因为另一个程序使用 DAT 文件。 Bash 脚本做得很完美,但该程序只能在 Windows 上运行。
  • 要将命令的输出捕获到变量中,请使用for /f。你需要delayed expansion
  • 这比我通常看到的 bash-to-batch 问题要付出更多努力。做得好。似乎您唯一真正的问题是弄清楚如何将命令的输出存储在变量中,可以找到here

标签: windows batch-file cmd


【解决方案1】:

我不熟悉exiftool,所以无法验证,但以下应该可以:

@echo off 
setlocal enabledelayedexpansion
for %%a in (*.mp3) do (
  for /f "usebackq delims=" %%b in (`exiftool -p Title '%%a'`) do set "title=%%b"
  for /f "usebackq delims=" %%b in (`exiftool -p Album '%%a'`) do set "Album=%%b"
  for /f "usebackq delims=" %%b in (`exiftool -p Artist '%%a'`) do set "Artist=%%b"
  (
    echo Lit=
    echo ENG=
    echo CRD=
    echo Title=!title!
    echo Album=!Album!
    echo Artist=!Artist!
  ) > "%%~dpna.dat"
)

注意:如果文件名或字符串包含感叹号,则会因扩展延迟而遇到问题。
如果您想避免延迟扩展(出于此或任何其他原因),您可以嵌套 for 循环并直接使用元变量:

@echo off 
for %%a in (*.mp3) do (
  for /f "usebackq delims=" %%b in (`exiftool -p Title '%%a'`) do (
    for /f "usebackq delims=" %%c in (`exiftool -p Album '%%a'`) do (
      for /f "usebackq delims=" %%d in (`exiftool -p Artist '%%a'`) do (
        (
          echo Lit=
          echo ENG=
          echo CRD=
          echo Title=%%b
          echo Album=%%c
          echo Artist=%%d
        ) > "%%~dpna.dat"
      )
    )
  )
)

【讨论】:

    【解决方案2】:

    您不必为每个MP3 文件执行三个单独的EXIFTool 迭代,而应该只需一个即可。除此之外,您不需要先选择*.mp3 文件,因为EXIFTool 已经可以选择目录中的所有文件。

    例如:

    @For /F Tokens^=2^,4Delims^=^" %%G In (
        'EXIFTool *.mp3 -j -album -artist -title 2^>NUL^|%__AppDir__%find.exe ":"'
    )Do @(Set "%%G=%%H"&SetLocal EnableDelayedExpansion&(Echo "Lit="&Echo "ENG="
            Echo "CRD="&Echo "TIT=!Title!"&Echo "ALB=!Album!"&Echo "ART=!Artist!"
        )>"!SourceFile:~,-4!.DAT"&EndLocal)
    

    假设输出示例:(13 Come Said The Boy.DAT)

    "Lit="
    "ENG="
    "CRD="
    "TIT=Come Said The Boy"
    "ALB=Just Great Australian Rock Songs Disc 2"
    "ART=Mondo Rock"
    

    【讨论】:

    • 我想知道exiftool 是否有这些功能,但我没有足够的好奇心去下载和安装它。这无疑是一种更好的方法。
    • 我快速浏览了它的命令行使用信息,这就是@Stephan。我这样做是因为老实说,我无法想象这个命令不能一次输出多个项目。我不得不假设 JSON 输出会更容易解析,(并且因为它显然更高效),因为它应该被双引号引起来,并且猜到其余的,因为我仍然不是 Windows PC 拥有者,(我所拥有的所有维修单位均未包含 EXIFTool
    【解决方案3】:

    将其编写为 pwsh 脚本将允许相同的脚本在 Linux、Mac、Windows 和其他系统上运行。 http://www.github.com/PowerShell/PowerShell/

    #!/bin/env pwsh
    function touch {
        Param(
            [Parameter(Mandatory=$true)]
            [string]$Path
        )
    
        if (Test-Path -LiteralPath $Path) {
            $NewDate = Get-Date
            (Get-Item -Path $Path).LastWriteTime = $NewDate
            (Get-Item -Path $Path).LastAccessTime = $NewDate
        } else {
            New-Item -Type File -Path $Path
        }
    }
    
    $Cwd = Get-Location
    $nl = [System.Environment]::NewLine
    
    Get-ChildItem -Recurse -File -Path $Cwd -Filter '*.mp3' |
        ForEach-Object {
            $TITLE = & exiftool -charset filename=cp1250 -p '$Title' $_.FullName
            $ALBUM = & exiftool -charset filename=cp1250 -p '$Album' $_.FullName
            $ARTIST = & exiftool -charset filename=cp1250 -p '$Artist' $_.FullName
    
            $DataFile = Join-Path -Path $_.Directory -ChildPath $($_.BaseName + '.DAT')
            if (Test-Path -Path $DataFile) { Remove-Item -Path $DataFile }
            touch $DataFile
    
            "Lit=${nl}lENG=${nl}CRD=${nl}Title=$TITLE${nl}Album=$ALBUM${nl}Artist=$ARTIST" |
                Out-File -FilePath $DataFile -Encoding ascii
        }
    

    我不确定是否需要 touch 操作。如果.DAT 文件存在,它将被覆盖。如果它不存在,它将被创建。如果是这样……

    $Cwd = Get-Location
    $nl = [System.Environment]::NewLine
    
    Get-ChildItem -Recurse -File -Path $Cwd -Filter '*.mp3' |
        ForEach-Object {
            $TITLE = & exiftool -charset filename=cp1250 -p '$Title' $_.FullName
            $ALBUM = & exiftool -charset filename=cp1250 -p '$Album' $_.FullName
            $ARTIST = & exiftool -charset filename=cp1250 -p '$Artist' $_.FullName
    
            $DataFile = Join-Path -Path $_.Directory -ChildPath $($_.BaseName + '.DAT')
    
            "Lit=${nl}lENG=${nl}CRD=${nl}Title=$TITLE${nl}Album=$ALBUM${nl}Artist=$ARTIST" |
                Out-File -FilePath $DataFile -Encoding ascii
        }
    

    【讨论】:

    • @lit 这些代码行 exiftool 在哪里给出了一些错误(关于代码页)。我添加了一个cp1250。其他问题与 ID3 标签有关。您的代码返回了代码中的内容这个词。它需要美元符号 '$' *** $TITLE = & exiftool -charset filename=cp1250 -p '$Title' $_.FullName $ALBUM = & exiftool -charset filename=cp1250 -p '$Album' $_.FullName $ARTIST = & exiftool -charset filename=cp1250 -p '$Artist' $_.FullName
    • 您对文件的编码输出是 ASCII 并以 Unix LF 结束。我正在尝试将 ASCII 更改为 ANSI 并将行从 Unix LF 结束到 Windows CR LF 我做不到。我用谷歌回答我该怎么做?但大多数答案都是 UTF8。你知道那个问题的解决方案吗?读取文件的程序看不到windows-1250以外代码页的文件。
    • 我很抱歉。我将输出更改为我们 0x0D0A 行结尾。也许单独输出这些行会更好,以便它们获得平台原生的行结尾。或者,也许 pwsh 有一个用于行尾的变量...
    • 将输出更改为使用系统原生换行符。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-01-05
    • 2013-11-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多