I want to add new lines after the <seq>
tag only if $mp3File.FullName
is not equal to $currentFileInPlaylist
. However, when the script logic returns false
(echoing "nothing to add"), file 1.wpl is still updating. Below is the complete code:
$folderPath = "C:\Users\user\Downloads\"
$playList = "C:\Users\user\Music\Playlists\1.wpl"
# If File with datetime when script was executed exists, get mp3 files created after script ran last time and store them in the $mp3Files variable
$scriptRunLastTimePath = "$folderPath\1.txt"
if (Test-Path $scriptRunLastTimePath -PathType Leaf) {
$dateToCompareWith = Get-Content -Path $folderPath\1.txt
$culture = [System.Globalization.CultureInfo]::InvariantCulture
$format = 'dd.MM.yyyy HH:mm:ss'
$storedDateTime = [DateTime]::ParseExact($dateToCompareWith, $format, $culture)
$mp3Files = @(Get-ChildItem -Path $folderPath -Filter "*.mp3" -File |
Where-Object { $_.LastWriteTime -gt $storedDateTime })
} else {
$mp3Files = Get-ChildItem -Path $folderPath -Filter "*.mp3" -File
}
($xml = [xml]::new()).Load($playList)
$currentFilesInPlaylist = $xml.SelectNodes("//seq/*").src
# If mp3 file is present in folder and not in 1.wpl, add the full file name to playlist file after the <seq> tag
foreach ($currentFileInPlaylist in $currentFilesInPlaylist) {
foreach ($mp3File in $mp3Files) {
if ($mp3File.FullName -ne $currentFileInPlaylist) {
(Get-Content $playlist) | Foreach-Object {
$_ # send the current line to output
if ($_ -match "<seq>") {
# Add lines after the selected pattern
' <media src="' + $mp3File.FullName + '"/>'
}
} | Set-Content $playList -Force
} else {
echo "nothing to add"
}
}
}
# Create a "checkpoint" file: Export the date and time the script was last run to the file
(Get-Date).ToString('dd/MM/yyyy HH:mm:ss') | Out-File -FilePath $scriptRunLastTimePath
1.wfl file:
<?wpl version="1.0"?>
<smil>
<head>
<meta name="Generator" content="Microsoft Windows Media Player -- 12.0.22621.1"/>
<meta name="ItemCount" content="2"/>
<title>Untitled playlist</title>
</head>
<body>
<seq>
<media src="C:\Users\user\Downloads\Katzianerova vojna.mp3"/>
<media src="C:\Users\user\Downloads\Rat i mir u povijesti III- dio.mp3"/>
</seq>
</body>
</smil>
EDIT
This approach also gives same results:
foreach ($currentFileInPlaylist in $currentFilesInPlaylist) {
foreach ($mp3File in $mp3Files) {
if ($mp3File.FullName -eq $currentFileInPlaylist) {
$updatedPlaylist = $updatedPlaylist -ne $currentFileInPlaylist # Remove matching file from updated playlist
echo "nothing to add"
}
}
}
foreach ($mp3File in $mp3Files) {
if ($updatedPlaylist -notcontains $mp3File.FullName) {
$mediaElement = '<media src="{0}"/>' -f $mp3File.FullName
(Get-Content -Path $playlist) | ForEach-Object {
$_
if ($_ -match "<seq>") {
$mediaElement
}
} | Set-Content -Path $playlist
Write-Host "Added file '$($mp3File.Name)' to the playlist."
} else {
Write-Host "File '$($mp3File.Name)' already exists in the playlist."
}
}
Even when variable content is in wpl file, file is being updated
output:
nothing to add
nothing to add
Added file 'Katzianerova vojna.mp3' to the playlist.
Added file 'Rat i mir u povijesti III- dio.mp3' to the playlist.
EDIT 2:
Made a small progress:
script now reports only one "loop" needs to be added to the file:
$filesAdded = $false # Initialize flag to track whether any files were added
foreach ($mp3File in $mp3Files) {
if ($currentFileInPlaylist -notcontains $mp3File.FullName) {
$mediaElement = '<media src="{0}"/>' -f $mp3File.FullName
(Get-Content -Path $playlist) | ForEach-Object {
$_
if ($_ -match "<seq>") {
$mediaElement
$filesAdded = $true # Set flag to indicate files were added
}
} | Set-Content -Path $playlist
Write-Host "Added file '$($mp3File.Name)' to the playlist."
} else {
Write-Host "File '$($mp3File.Name)' already exists in the playlist."
}
}
if (-not $filesAdded) {
Write-Host "No files were added to the playlist."
}
Output:
Added file 'Katzianerova vojna.mp3' to the playlist.
File 'Rat i mir u povijesti III- dio.mp3' already exists in the playlist.
>Solution :
The problem is that you compare each .mp3
file path from your disk against each and every file path from the playlist: Even if you find a given file in the playlist and therefore skip it, all the other iterations of your loop will not skip it.
You can avoid the problem by:
-
omitting the outer
foreach
loop altogether -
using the
-notin
operator to test the presence of a given file in the playlist.
foreach ($mp3File in $mp3Files) {
# Note the use of -notin and the *whole array* of files in the playlist.
if ($mp3File.FullName -notin $currentFilesInPlaylist) {
(Get-Content $playlist) | Foreach-Object {
$_ # send the current line to output
if ($_ -match "<seq>") {
# Add lines after the selected pattern
' <media src="' + $mp3File.FullName + '"/>'
}
} | Set-Content $playList -Force
} else {
echo "nothing to add"
}
}