What can I do to automatic run a bat file when a new item on a folder is added? - powershell

I have a ps1 file which contains the code and a bat file which when i double click runs the code.
The ps1 file renames all files in that folder.
Here is the code:
get-childitem -path C:\Users\ASUS\Videos\Downloads\*.mp4 | foreach {rename-item $_ $_.name.replace("_"," ")}
How can I run the bat file to automatically rename all files that are added to that folder?

I saw #olaf mentioned FileSystemWatcher and, honestly, it one of the better options for what you're trying to do.
Alternatively, you can use Task Scheduler to run at specific times, dates, actions, etc. There's also no need to point to the bat file, it can run ps1 files just as easy without having to have .bat execute the .ps1.
Change your ps1 to the following. It's passing only the items that were created less than 30 minutes ago; can be changed to days, minutes, etc. Then, it's just renaming them(:
Get-ChildItem -Path C:\Users\ASUS\Videos\Downloads\*.mp4 | Where-Object {$_.CreationTime -gt (Get-Date).AddMinutes(-30)}| foreach {rename-item $_.FullName $_.name.replace("_"," ")}

Related

Powershell Script: Search for BATs with specific name and run them

back with another request to try and make my life a little easier. The problem: one of the programs I use deposits BMPs (yes, bitmaps, this is an ancient app, and no, I can't configure it not to make BMPs) where I don't need them. I've got a BAT file that can sweep a folder and remove them, but what I'd really like to do is put a copy of said BAT file in each folder where it leaves them, and then every time I run a backup cycle, have it search for those BAT files, and wherever it finds one, run it. (I'd also need to know how to tell it "look in the same folder you're in"--I think I can do that by something like $searchfolder = "." but please correct me if I'm wrong)
I'm guessing this is a Get-Childitem and ForEach, but I've taken a few stabs at it and it won't work. Does anyone have an idea how to go about it?
This is what I've got so far for the parent script to find all instances of "Clear_BMPs.bat":
Get-ChildItem $sourceDir -Include Clear_BMPs.bat -Recurse | ForEach-Object { call "Clear_BMPs.bat" }
And this is what I've got in the child script, to get rid of the BMPs themselves (the filename for it is "Clear_BMPs.bat":
$searchfile = "*.bmp"
$targetdir = ".\"
Get-ChildItem $targetdir -Include $searchfile | foreach{ "Removing file $($_.FullName)"; Remove-Item -force $_}
I'm still trying to get the Clear_BMPs.bat files to work properly but in my vision it will only search the root of the folder it's in, and not recurse through subdirectories.
Since you're calling from PowerShell, there's no reason to involve batch files, given that the code is under your control.
Indeed, what you show as the content of a Clear_BMPs.bat batch file is PowerShell code, which means you need to store it in a .ps1 file, not a .bat file.
Therefore, your recursive invocation that executes all .ps1 files should look like this:
# Find all 'Clear_BMPs.ps1' scripts in the subdir. tree of $sourceDir
# and invoke them.
Get-ChildItem -Recurse -LiteralPath $sourceDir -Filter Clear_BMPs.ps1 |
ForEach-Object { & $_.FullName }
And the Clear_BMPs.ps1 files in the various directories should contain:
# Remove all *.bmp files from the same dir. in which this .ps1 script is located.
Remove-Item -Path "$PSScriptRoot/*.bmp"
Note the use of the automatic $PSScriptRoot variable, which refers to the directory in which the enclosing .ps1 file is located.

Is there a PowerShell command that will delete CSV files after importing them?

I am looking for a way to delete the CSV files from a folder after they have been imported in to my script.
A little bit of background as to what I am hoping to achieve overall...
I am looking to have our database system export individual .csv files as and when they are processed. These will all be exported to the same folder. My PowerShell script will then run on a schedule, and will pick up any .csv files that are in specified folder, process these leavers in Active Directory and also remove their Home Directories from the server they are stored on, and then I would like those .csv files that have been processed to be deleted so the script doesn't attempt to process them again.
The code I have so far for importing the .csv files is as follows:
Get-ChildItem -Path 'C:\Scripts\Leavers\ -Filter '*.csv' | out-null
Import-CSV -Path (Get-ChildItem -Path 'C:\Scripts\Leavers\' -Filter '*.csv').FullName | out-null
This checked the Leavers folder for any .csv file and then imports all the data from these files.
How do I then tell the script to remove these files after importing? Bearing in mind that other .csv files may have been added to that directory in the meantime so I can't just remove all from the folder, it has to be the ones that have been imported.
I am also not sure whether this is placed directly after the import or at the end of the script.
Thank you
This is pretty straight forward. My concerns lie on what you would do after the import of the files but, that's on you to decide. Here's an approach which will import the csv's, do some code, and remove the file afterwards:
Get-ChildItem -Path 'C:\Scripts\Leavers\' -Filter '*.csv' |
ForEach-Object -Process {
Import-Csv -LiteralPath $_.FullName
#code here
Remove-Item -LiteralPath $_.FullName
}
Using Foreach-Object gives you more options to process the import by referencing the current objects properties ($_.FullName - file path). All that's left is to import the file using Import-Csv, do some extra code, then use the same $_.FullName property to remove the file.

Enter individual folder(s) and execute PowerShell command

I have many folders with even more subfolders, and as posted in my first question
How to create a powershell script / or windows .bat file for ffmpeg
I want to encode all video files in the folders.
The Script I got from mklement0 works fine but lazy as I am, I was wondering if there was a way to tell the PowerShell to enter folder 1, go to subfolder_1, and execute the ps1 script (would be perfect if it executed in a new powershell instance), wait a certain time and go into subfolder_2
Repeat until no more subfolders available.
Is this possible?
Edit:
The Script I got:
Get-ChildItem *.mkv | where BaseName -notlike '*`[encoded]' | foreach {
ffmpeg -i $_ -c:v libx265 -c:a copy -x265-params crf=25 "$($_.BaseName)[encoded].mkv"
pause
}
What is the reason for the desire to process each subfolder in a separate instance of powershell.exe? by Mathias R. Jessen
Because I want to encode multiple folders at once to save some time.
If there is a way to execute the script in the same PowerShell (as far as my understanding goes, I can only encode one folder at one time if I use the same PowerShell instance)
You could wrap the whole thing in another Get-ChildItem to find all the subdirectories in your main folder, then set-location to that path and run in each of those:
$directories = get-childitem -path "C:\Path\To\Videos\Folder" -Recurse -Directory
Foreach ($dir in $directories) {
Set-Location $dir.fullname
*Run your code here*
}
This would be better than trying to do them all in parallel with different PowerShell instances. Correct me if I'm wrong, but video encoding uses a lot of your computer's resources, so trying to run them in parallel would actually be more of a hindrance.

If a file is present move another file in another folder

in a particular folder I have files created with random name for example:
file1.xml
file2.xml
when these files are succesfully created, a .ack file is created.
So I will have
file1.xml
file1.ack
file2.xml
file2.ack
What I have to do:
Move a .xml file only if the corresponding .ack is created.
The difficult part: file names are random and I have no control over them.
Is there a way to create a .bat or a powershell to check and move with these requirements run at scheduled times?
Many thanks for your help
the ideal would be a powershell task, indeed. Now, you will want to leverage window's Scheduled Tasks in order to run it at a scheduled time.
In a nutshell, what you'll have to do with powershell is to
List the xml files in your folder with Get-ChildItem -filter "*.xml"
Pipe it to a Where-Object statement to make sure the .xml has a .ack counterpart, leveraging Test-Path
For each produced item, move the .xml file.
Move-Item -Path $source -Destination $target
Optionally, you could also clean the .ack files with Remove-Item.
Find every filename that appears with two extensions, and move them both.
gci | group basename |? Count -eq 2 | select -expand group | move -Dest c:\temp
Because it's fun not to use any loops. If you want loops, maybe: to move the XML and delete the .ack.
gci *.ack |% { move ($_.BaseName +'.xml') "c:\temp" ; rm $_ }

Rename first 20 characters of every filename in a file

I am trying to write a script in powershell to remove the first 20 characters of every MP3 filename in a folder, I have created a file 'test.ps' and inserted the powershell code below into it,
gci *.mp3 | rename-item -newname { [string]($_.name).substring(20) }
When I run this file in powershell.exe nothing happens,
Can anyone help? Thanks.
This may get you started. (There are probably much more concise ways, but this works and is readable when you need to maintain it later. :-) )
I created a folder C:\TempFiles, and created the following files in that folder:
TestFile1.txt
TestFile2.txt
TestFile3.txt
TestFile4.txt
(I created them the old-fashioned way, I'm afraid. <g>. I used
for /l %i in (1,1,4) do echo "Testing" > TestFile%i.txt
from an actual command prompt.)
I then opened PowerShell ISE from the start menu, and ran this script. It creates an array ($files), containing only the names of the files, and processes each of them:
cd \TempFiles
$files = gci -name *.txt
foreach ($file in $files) {
$thename = $file.substring(4);
rename-item -path c:\TempFiles\$file -newname $thename
}
This left the folder containing:
File1.Txt
File2.Txt
File3.Txt
File4.Txt
File5.Txt
In order to run a script from the command line, you need to change some default Windows security settings. You can find out about them by using PowerShell ISE's help file (from the menu) and searching for about_scripts or by executing help about_scripts from the ISE prompt. See the sub-section How To Run A Script in the help file (it's much easier to read).
Your code actually works. Two things...
Rename the file to test.ps1.
Run it in the folder you have your MP3 files in. Since you didn't provided a path to Get-ChildItem it will run in the current directory.
I tested your line by making a bunch of mp3 files like this -
1..30 | % { new-item -itemtype file -Name (
$_.ToString().PadLeft(30, 'A') + ".mp3" )}
I would use a more "safer" way (you'll get an error if the file name is shorter than the length in question, you are also targeting the file extension as a part of the total characters). Check if the base name of each file is greater than 21 characters (if you remove the first 20 it can be still have a name with one character long). It can fail if the directory contains a file with same name after you removed the first 20, you can develop it further on your own):
gci *.mp3 | foreach{
if($_.BaseName.Length -ge 21)
{
$ext = $_.Extension
$BaseName = $_.BaseName.Substring(20)
Rename-Item $_ -NewName "$BaseName$ext"
}
}
// delete (replace with empty char) first 20 charters in all filename witch is started with "dbo."
// powershell
Get-ChildItem C:\my_dir\dbo -Recurse -Force -Filter dbo.* | Where-Object {!$_.PSIsContainer} | Rename-Item -NewName { ($_.name).Substring(20) }