12
votes

I need a PowerShell script to export a list of file names only with no file extension then output to a text file separate for each sub-folder. I need to specify a parent directory in the script, then PowerShell needs to go off and create a separate text file for each sub folder using the the name of the sub folder for the text file name (with no spaces and lowercase). Then in each sub-folder based text file created, have a list of file names that are contained in each sub-folder with no file extension.

$files = Get-ChildItem -Path "M:\Music" -Recurse `
| Where-Object {`
    $_.DirectoryName -notlike "*Other\Children" -and `
    $_.DirectoryName -notlike "*Other\Numbers" -and `
    $_.Extension -eq ".mp3"}
#Now loop through all the subfolders
$folder = $files.PSisContainer
ForEach ($Folder in $files)
{
$ParentS = ($_.Fullname).split("\")
$Parent = $ParentS[@($ParentS.Length - 2)]
Select-Object BaseName > C:\Users\me\Documents\$parent.txt
}

OK, spent some more time on this, script is added below to the previous attempt. Seems I am very close this time, however writing to the text file at the end is not 100%, I was using Out-File before which was leaving a blank line at the bottom of each text file which I didn't want. Why I switched to [system.io.file]::WriteAllText and [system.io.file]::AppendAllText, however each of these have their idiosyncrasies which don't do what I need. In the Text file I need the list of files in one column with no blank lines.

$files = Get-ChildItem -Path "M:\Music" -Recurse `
| Where-Object {`
    $_.DirectoryName -notlike "*Other\Children" -and `
    $_.DirectoryName -notlike "*Other\Numbers" -and `
    $_.Extension -eq ".mp3"}
#Now loop through all the subfolders
$folder = $files.Directory
ForEach ($Folder in $files)
{
$ParentS = ($folder.Fullname).split("\")
$ParentT = $ParentS[(@($ParentS.Length - 2))]
$Parent = $ParentT.replace(' ','')
[system.io.file]::WriteAllText("C:\Users\me\Documents\$parent.txt", $folder.BaseName,                                            [System.Text.Encoding]::Unicode)
}
1
This site is not for "request for scripts". Show us what you tried, where you failed and what is not working. Then, we can try to point you in right direction or review the script and provide some hint.AlexPawlak
This is what happened last time, I had a requirement, and someone gave me a script. Ok, I'll share the script here shortly when in front of my computer.Marc Kean
Well, if you look at some "high quality" questions, (like stackoverflow.com/questions/11227809/…) this can give you a good overview on what this site is meant to be.AlexPawlak
This is what I have so far, but can't seem to work out how to list file names to different text files based on the different folders. I added my script aboveMarc Kean
OK, spent some more time on this, script is added below to the previous attempt. Seems I am very close this time, however writing to the text file at the end is not 100%, I was using Out-File before which was leaving a blank line at the bottom of each text file which I didn't want. Why I switched to [system.io.file]::WriteAllText and [system.io.file]::AppendAllText, however each of these have their idiosyncrasies which don't do what I need. In the Text file I need the list of files in one column with no blank lines.Marc Kean

1 Answers

21
votes

What a good opportunity to show off the richness of Powershell and .NET working together.

First off, the easiest way to get the full names of all the subfolders of a folder is with a line like this:

$folders = (Get-ChildItem -Directory -Recurse M:\Music).FullName

-Directory limits what is returned to an array of DirectoryInfo object. By taking advantage of Powershell's ability to return only the FullName property, we can return an array of folder paths all in one statement

We can create the files listing the songs in the directory with just a few more lines of code:

foreach ($folder in $folders)
{
    $fileBaseNames = (Get-ChildItem $folder\*.mp3).FullName | % {[System.IO.Path]::GetFileNameWithoutExtension($_)}
    $catalogFileName = (Split-Path $folder -Leaf) -replace ' ',''
    if ($fileBaseNames)  {Set-Content -Path $folder\$catalogFileName.txt -Value $fileBaseNames}
}

We visit each subfolder and for every subfolder we:

  • Get an array of the mp3 file names (without file extension) in the current directory. (I love .NET's GetFileNameWithoutExtension method at times like this.
  • Create the file name for our catalog by isolating the current folder name (Split-Path -Leaf) and sucking out all the spaces by replacing each space with an empty string.
  • Finally if our list of songs isn't empty we save it off with Set-Content, a great way to save a list of anything.

It never ceases to amaze me how powerfull and concise Powershell is. The line creating the $fileBaseNames may be a little gnarly for some, but it would be an easy enough thing to turn the foreach-object construct into an easy to ready multiline foreach clause.