如何使用 PowerShell 从文件中过滤字符串?

如何使用 PowerShell 从文件中过滤字符串?

我正在尝试解析一个名为 playlist.xml 的播放列表文件。我想从这个文件中过滤包含在 中的 和 .mp3 文件。实际上,$PlaylistPath 下有许多 playlist.xml 文件。我尝试使用 Get-Content、Select-String、Get-Childitem 和其他 cmdlet,但无济于事。下面显示的是我为此目的使用 PowerShell 的微不足道的尝试。

任何帮助将不胜感激!

$PlaylistPath = "\\MYNAS\Backups\Emby\Emby Backup - 2020-05-29 02.0.0 - Auto\playlists"
$OutputPath = "C:\Users\bernie\Desktop\playlists"

(Select-String -Path "C:\Users\bernie\Desktop\playlist.xml" -Pattern '^<Local').Line | Set-Content C:\Users\bernie\Desktop\Output.txt

# $FileNames = Get-Childitem -Path "playlists" -Include playlist.xml -File -Recurse | Select -exp Name 

#$FileNames = Get-ChildItem $PlaylistPath -Filter playlist.xml -Recurse | % { $_.FullName }

foreach ($file in $FileNames) {

(Select-String -Path $file -Pattern 'LocalTitle').Line | Write-Output
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<Item>
  <Added>5/23/2020 9:49:16 PM</Added>
  <LockData>false</LockData>
  <LocalTitle>Andy Timmons Playlist</LocalTitle>
  <RunningTime>32</RunningTime>
  <Genres>
    <Genre>Pop</Genre>
    <Genre>Rock</Genre>
  </Genres>
  <Studios>
    <Studio>Favored Nations Records</Studio>
  </Studios>
  <PlaylistItems>
    <PlaylistItem>
      <Path>/volume1/Media Library/Music Library Bernie/Andy Timmons/Resolution/01 Deliver Us.mp3</Path>
    </PlaylistItem>
    <PlaylistItem>
      <Path>/volume1/Media Library/Music Library Bernie/Andy Timmons/Resolution/02 Helipad.mp3</Path>
    </PlaylistItem>
    <PlaylistItem>
      <Path>/volume1/Media Library/Music Library Bernie/Andy Timmons/Resolution/05 Redemption.mp3</Path>
    </PlaylistItem>
    <PlaylistItem>
      <Path>/volume1/Media Library/Music Library Bernie/Andy Timmons/Ear X-Tacy/01 - Carpe Diem.mp3</Path>
    </PlaylistItem>
    <PlaylistItem>
      <Path>/volume1/Media Library/Music Library Bernie/Andy Timmons/Ear X-Tacy/05 - Farmer Sez.mp3</Path>
    </PlaylistItem>
  </PlaylistItems>
 </Item>

答案1

PowerShell:轻松解析 XML 元素值

首先,您提供的示例 XML 内容似乎格式不正确,因此我认为这只是一个粘贴问题,因此我通过关闭该示例中的</PlaylistItems>和元素来更正它。</Items>

诀窍是使用获取内容读取 XML 文件的内容,然后将其设置为变量转换为 XML 数据类型. 然后你可以使用该变量的DocumentElement 方法明确遵循元素路径的其余部分从所需元素中获取值,这很简单。

因此,一旦你有了播放列表标题或名称mp3 文件路径列表,您可以使用这些值进入文件或其他任何内容,但这是一种通过一些控制来解析 XML 文件的简单方法。

电源外壳

$PlaylistPath = "C:\Test\zzz\TestPlayList.xml";
[xml]$xml = Get-Content -LiteralPath $PlaylistPath;

$LocalTitle = $Xml.DocumentElement.LocalTitle;
$MP3Path    = $Xml.DocumentElement.PlaylistItems.PlaylistItem.Path;

$LocalTitle;
$MP3Path;

全部playlist.xml循环

 $PlaylistPath = "C:\Test\zzz" 
 $XMLFiles = Get-ChildItem -LiteralPath $PlaylistPath -Include playlist.xml -File -Recurse; 
 
 $XMLFiles | % { Process {
   [xml]$xml = Get-Content -LiteralPath $_.FullName;
   $LocalTitle = $Xml.DocumentElement.LocalTitle; 
   $MP3Path = $Xml.DocumentElement.PlaylistItems.PlaylistItem.Path;
   New-Item -Path "$OutputPath\$LocalTitle" -ItemType Directory -ErrorAction SilentlyContinue;
   $MP3Path | % { Copy-Item -LiteralPath "\$($_.Replace("volume1", "ds418").Replace("/", "\"))" "$OutputPath\$LocalTitle"; };  
   ##$LocalTitle; 
   ##$MP3Path;
   }};

输出(使用$LocalTitle$MP3Path

Andy Timmons Playlist
/volume1/Media Library/Music Library Bernie/Andy Timmons/Resolution/01 Deliver Us.mp3
/volume1/Media Library/Music Library Bernie/Andy Timmons/Resolution/02 Helipad.mp3
/volume1/Media Library/Music Library Bernie/Andy Timmons/Resolution/05 Redemption.mp3
/volume1/Media Library/Music Library Bernie/Andy Timmons/Ear X-Tacy/01 - Carpe Diem.mp3
/volume1/Media Library/Music Library Bernie/Andy Timmons/Ear X-Tacy/05 - Farmer Sez.mp3

起始 XML

<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<Item>
  <Added>5/23/2020 9:49:16 PM</Added>
  <LockData>false</LockData>
  <LocalTitle>Andy Timmons Playlist</LocalTitle>
  <RunningTime>32</RunningTime>
  <Genres>
    <Genre>Pop</Genre>
    <Genre>Rock</Genre>
  </Genres>
  <Studios>
    <Studio>Favored Nations Records</Studio>
  </Studios>
  <PlaylistItems>
    <PlaylistItem>
      <Path>/volume1/Media Library/Music Library Bernie/Andy Timmons/Resolution/01 Deliver Us.mp3</Path>
    </PlaylistItem>
    <PlaylistItem>
      <Path>/volume1/Media Library/Music Library Bernie/Andy Timmons/Resolution/02 Helipad.mp3</Path>
    </PlaylistItem>
    <PlaylistItem>
      <Path>/volume1/Media Library/Music Library Bernie/Andy Timmons/Resolution/05 Redemption.mp3</Path>
    </PlaylistItem>
    <PlaylistItem>
      <Path>/volume1/Media Library/Music Library Bernie/Andy Timmons/Ear X-Tacy/01 - Carpe Diem.mp3</Path>
    </PlaylistItem>
    <PlaylistItem>
      <Path>/volume1/Media Library/Music Library Bernie/Andy Timmons/Ear X-Tacy/05 - Farmer Sez.mp3</Path>
    </PlaylistItem>
  </PlaylistItems>
 </Item>

支持资源

答案2

皮条客果汁 IT,

以下是处理 Emby 播放列表文件的完整循环,引用我的 Synology NAS 上的 linux 路径,然后将它们转换为 windows 可以理解的 UNC 路径:

# These loops process the playlist.xml files.
$XMLFiles | % { Process { 
    [xml]$xml = Get-Content -LiteralPath $_.FullName
    $LocalTitle = $Xml.DocumentElement.LocalTitle 
    Write-Host "Copying playlist music files to: " $OutputPath/$LocalTitle
    New-Item -Path $OutputPath\$LocalTitle -ItemType Directory -ErrorAction SilentlyContinue | Out-Null
    $MP3Path = $Xml.DocumentElement.PlaylistItems.PlaylistItem.Path

    # This translates the Linux literal paths required by Get-Content and Copy-Item to UNC paths accessible in 
    # Windows.  Also, most music files are prefixed with a number, cauing the playlists to out of sequence.  
    # A numeric prefix is prepended here to each music file resulting in a playing order consistent with the 
    # Emby playlist.

    $counter = 1

    foreach ($path in $MP3Path) {   
       $OutputFile = Split-Path $path -Leaf
       $OutputFile = ([string]$counter).PadLeft(2,'0') + " - " + $OutputFile 
       $OutputFile = $OutputPath + "\" + $LocalTitle + "\" + $OutputFile

       Copy-Item -LiteralPath "\$($path.Replace("volume1", "ds418").Replace("/", "\"))" $OutputFile
      
       $counter++
    }

}};


Write-Host "`nDone"

相关内容