how to find all .bat files and execute them one by one? - powershell

I am still very new to PowerShell and need some help.
I have some .bat files in a folder called: c:\scripts\run\
and I want to run them one by one but I don't know how many I have, it changes from time to time.
So I want to run a loop with foreach like this:
foreach ($file in get-childitem c:\scripts\run | where {$_.extension -eq ".bat"})
But I don't know how to run them now.
I know that I can run them 1 by 1 like this :
./run1.bat
./run2.bat
./run3.bat
But how do I implement that?
Thanks!!

Try this:
Get-Childitem -Path c:\scripts\run -Filter *.bat | % {& $_.FullName}

You can use
& $file.FullName
within your loop.
I would probably just use a pipeline, though, instead of an explicit foreach loop:
Get-ChildItem C:\scripts\run -Filter *.bat | ForEach-Object { & $_.FullName }
If you want additional checks after each batch file ran:
gci C:\scripts\run -fi *.bat | % {
& $_.FullName
if (Test-Path C:\scripts\run\blah.log) {
...
}
}

Related

File Sorting Based on Similar File and Folder Names

Im still generally new to powershell, and I am trying to create a program that will take files based on their name, and move them into folders that have a similar name but not exactly the same.
For example, Lets say I have 3 files, Apples.txt, Grapes.txt, and Oranges.txt. And I want to move them into corresponding folders, ApplesUSA, GrapesNY, OrangesFL.
I could just hard code it using a loop and a If-Then Statement. i.e If Apples.txt exists move to ApplesUSA. But I want it to be dynamic, so if other files and folders are added later I dont have to update the code. Is there a way to write a statement that would say if FileA and FolderB are similar in name (both contain apples in the name somewhere) then move fileA to FolderB and so on.
Any help appreciated. Thanks!!!!
try Something like this
$PathWithFile="C:\temp\Test"
$PathWithDir="C:\temp\Test"
Get-ChildItem $PathWithFile -file -Filter "*.txt" | %{
$CurrentFile=$_
$Dirfounded=Get-ChildItem $PathWithDir -Directory | where {$_ -match $CurrentFile.BaseName} | select FullName -First 1
if ($Dirfounded -ne $null)
{
move-Item $CurrentFile.FullName -Destination $Dirfounded.FullName -WhatIf
}
}
A oneliner similar to #Esperento's
gci *.txt -af|%{$File=$_.FullName;gci "$($_.BaseName)*" -ad|%{Move $File -Dest $($_.FullName) -whatif}}
The verbose version:
PushD "X:\path\to\base\folder"
Get-ChildItem *.txt -File | ForEach-Object{
$File = $_.FullName
Get-ChildItem "$($_.BaseName)*" -Directory | ForEach-Object {
Move-Item $File -Destination $_.FullName -whatif
}
}
PopD
Both versions require PowerShell V3 for the -File and -Directory parameters (and their aliases -af/-ad) This can be substituted by an additional |Where-Object{ $_.PSIsContainer} respective | Where-Object{!$_.PSIsContainer}

Powershell tail multiple files command

I can tail one file via the following command:
Get-Content -Path C:\log1.txt -Tail 10 –Wait
How do I extend this to multiple files, I have tried the following with no luck:
Get-Content -Path C:\log1.txt,C:\log2.txt -Tail 10 –Wait
This will only pick up updates from the first file, not the second.
Based on #mjolinor's comment, I have come up with the following that appears to work,
Workflow My-Tail
{
Param([string[]] $Path)
foreach -parallel ($file in $path)
{
Get-Content -Path $file -Tail 1 -Wait
}
}
My-Tail (dir C:\*.log -Include log1.txt,log2.txt)
However, this has some sort of progress bar that appears...
I can't speak to how efficient this is, but since I'm using PowerShell Core 7.1.3, I can't use Workflows or ForEach -Parallel, but I can use ForEach-Object -Parallel, so I tried it just to see what would happen...
gci -Path C:\ -Filter log*.txt |
% -Parallel {
cat -Wait -Tail 10 -Path $_
} -ThrottleLimit 30
In my case, I had 27 files I needed to monitor, so I chose a number just above that, and this seemed to work.
Just to be sure it was working, I used this, which will output the source file name before each line:
gci -Path C:\ -Filter log*.txt |
% -Parallel {
$file = $_;
cat -Wait -Tail 10 -Path $file |
% { write "$($file.Name): ${_}" }
} -ThrottleLimit 30
I needed tailed output across multiple files and I wanted to try do it in one line,
here's what I eventually came up with:
gci *.txt -recurse | ForEach-Object { Write-Output "$_`n" + $(Get-Content $_ -tail 5) + "`n" }
Its takes a recursive directory listing of all files named *.txt,
writes the file path to console,
then writes the last 5 lines to console.
I didn't need to follow the tails of the files, they weren't being actively written to.

Delete files defined in an array with Powershell

Is it possible to define an array of filenames (all files in different folders) and then in a loop delete them all, or do something else?
Actually I need to create a few symbolic links using mklink to one file, putting those links in a different folders, replacing the old links if there was any.
Deleting an array of filenames is simple:
Remove-Item foo.txt,c:\temp\bar.txt,baz\baz.txt
Or via a variable:
$files = 'foo.txt','c:\temp\bar.txt','baz\baz.txt'
Remove-Item $files
And then based on all files in different folders:
$folders = 'C:\temp','C:\users\joe\foo'
Get-ChildItem $folders -r | Where {!$_.PSIsContainer} | Remove-Item -WhatIf
Remove the -WhatIf to do the actual removal.
If you want to delete a file with a specific name you could use the -Filter parameter on Get-ChildItem. This would be the best performing approach:
$folders = 'C:\temp','C:\users\joe\foo'
Get-ChildItem $folders -r -filter foo.bak | Remove-Item -WhatIf
If the name requires more sophisticated matching then you can use a regex in a Where scriptblock e.g.:
$folders = 'C:\temp','C:\users\joe\foo'
Get-ChildItem $folders -r | Where {$_.Name -match 'f\d+.bak$'} |
Remove-Item -WhatIf
something like this should work:
can't test right now, sorry
$filenames = #('filename1.txt', 'filename2.txt', 'filename3.txt')
foreach($file in $filenames)
{
#GCI recursive to find all instances of this filename
$filesToDelete = Get-ChildItem -R | where {$_.Name -eq $file}
foreach($f in $filesToDelete)
{
#delete the file that matches, etc. here
# just using Write-Host to echo out the name for now
Write-Host $f.Name
}
}
As with most powershell, you can really compress this, but wanted to extend for explanation.
You could extend this to match your needs. For example if you needed all files that contain the word "delete", you could do gci | where {$_.Name -like "$file"}

powershell script delete folders regular expression

I've written a Powershell script to delete subfolders within a given folder whose name starts with either 0 or 1. This script seems to work only for non-empty folders. I want it to delete the inner contents too. Is there any switch that makes it possible? Also, for some files, I get an error about not having enough permissions whereas the script runs as an administrator.
$srcFolder = "C:\Documents and Settings\setup\Desktop\Temp\"
$folderList = Get-Childitem $a | Where-Object {$_.Name -match "^[01]"}
foreach( $folder in $folderList)
{
$tempFolder = $srcFolder + $folder;
Remove-Item $tempFolder
}
Any ideas?
Regards,
Sujeet Kuchibhotla
You can simplify this quite a bit:
Get-ChildItem $srcFolder | Where {$_.PSIsContainer -and ($_ -match '^[01]')} |
Remove-Item -Recurse -WhatIf

Powershell v1 - deleteing all files & folders except in a named folder

I want to delete all the content and the children of a given root folder, however i want to keep some files (the logs), which all reside in a logs folder
What is the elegant way of doing this in powershell.
Currently i am doing it in multile steps, surely this can be done easily... i have a feeling my oo-ness/language bias is getting in the way
eg
c:\temp
c:\temp\logs
c:\temp\logs\mylog.txt
c:\temp\logs\myotherlog.log
c:\temp\filea.txt
c:\temp\fileb.txt
c:\temp\folderA...
c:\temp\folderB...
after delete should just be
c:\temp
c:\temp\logs
c:\temp\logs\mylog.txt
c:\temp\logs\myotherlog.log
this should be simple; i think 12:47am-itis is getting me...
Thanks in advance
RhysC
dir c:\temp | where {$_.name -ne 'logs'}| Remove-Item -Recurse -force
Here is a general solution:
function CleanDir($dir, $skipDir) {
write-host start $dir
Get-ChildItem $dir |
? { $_.PsIsContainer -and $_.FullName -ne $skipDir } |
% { CleanDir $_.FullName $skipDir } |
? { $skipDir.IndexOf($_, [System.StringComparison]::OrdinalIgnoreCase) -lt 0 } |
% { Remove-Item -Path $_ }
Get-ChildItem $dir |
? { !$_.PsIsContainer } |
Remove-Item
$dir
}
CleanDir -dir c:\temp\delete -skip C:\temp\delete\logs
It works recursivelly. The first parameter to CleanDir is the start directory. The second one ($skipDir) is the directory that should not be deleted (and its content shouldn't be as well).
Edited: corrected confusing example ;)