Reputation: 14549
I have a function that lets me write the file-path of files to a text file, depending on your input. That sounds confusing, but I don't know of a better way to put it, so here's the function:
Function writeAllPaths([string]$fromFolder,[string]$filter,[string]$printfile) {
Get-ChildItem -Path $fromFolder -Recurse $filter | Select-Object -Property FullName > $printfile
}
First argument being the folder you start your search from.
Second argument, the filter. *.zip for instance, will list all zip files.
Third argument, you have to provide where the text file will end up.
Sample usage: writeAllPaths c:\ *.zip c:\allZips.txt
The thing is, when I do this, Powershell won't accept commands until it's done. Which isn't very productive. Is there a way to have this run in the background when started. And preferably, give a little message when it's done. I could be opening any file that's being created in the middle of the process...
Also, I'm on Windows 7, so I'm guessing that I have Powershell 2.0
Yeah, I'm not sure about it :p
EDIT:
I used Start-Job, as suggested, as follows:
Function writeAllPaths([string]$fromFolder,[string]$filter,[string]$printfile) {
Start-Job -ScriptBlock {Get-ChildItem -Path $fromFolder -Recurse $filter | Select-Object -Property FullName > $printfile}
}
However, the file isn't created. The old function does create a file.
EDIT2: it would be preferable to have this function in my Powershell profile. This way, I can execute it whenever I want, instead of having to load in the specific ps1 file every time I boot Powershell.
More info on the Powershell profile can be found here
You can summon your own profile by typing: notepad $profile
Upvotes: 4
Views: 15699
Reputation: 202082
In the new scope you create for the background job, your parameters defined for you WriteAllPaths function are not defined. Try this and you'll see they aren't:
Function writeAllPaths([string]$fromFolder,[string]$filter,[string]$printfile)
{
Start-Job { "$fromFolder, $filter, $printFile" }
}
$job = WriteAllPaths .\Downloads *.zip zips.txt
Wait-Job $job
Receive-Job $job
, ,
Try this instead:
Function writeAllPaths([string]$fromFolder, [string]$filter, [string]$printfile)
{
Start-Job {param($fromFolder,$filter,$printfile)
"$fromFolder, $filter, $printfile" } `
-ArgumentList $fromFolder,$filter,$printfile
}
$job = WriteAllPaths .\Downloads *.zip z.txt
Wait-Job $job
Receive-Job $job
.\Downloads, *.zip, z.txt
Now you see your output because we passed the parameters through to the scriptblock via -ArgumentList. What I would recommend is a function that can optionally use a background job. Just stick this function definition in your profile and you're set:
function WriteAllPaths([string]$FromFolder, [string]$Filter,
[string]$Printfile, [switch]$AsJob)
{
if (![IO.Path]::IsPathRooted($FromFolder)) {
$FromFolder = Join-Path $Pwd $FromFolder
}
if (![IO.Path]::IsPathRooted($PrintFile)) {
$PrintFile = Join-Path $Pwd $PrintFile
}
$sb = {
param($FromFolder, $Filter, $Printfile)
Get-ChildItem $FromFolder -r $filter | Select FullName > $PrintFile
}
if ($AsJob) {
Start-Job $sb -ArgumentList $FromFolder,$Filter,$PrintFile
}
else {
& $sb $FromFolder $Filter $PrintFile
}
}
Test the function (synchronously) like so:
$job = WriteAllPaths Downloads *.zip z.txt -AsJob
Wait-Job $job
Receive-Job $job
Note that I'm testing if the path is root and if not I'm prepending the current dir. I do this because the background job's starting dir is not always the same as where you executed Start-Job from.
Upvotes: 6