How can i divide copying files into priorities to copy different files - arrays

Im trying to build a way to create a folder structure in windows automatically absed on a job number and how many parts they will need. im able to get the code functioning to the point where i make the main folder, the sub folder and the sub folder in the folders with a part in it. the thing im looking to do however is transfer a different part into each folder based on priorities
There are max 7 priorities and that needs to be divided by how many parts so example would be there are 4 parts with 4 priorities.. (in this sample code it creates the sales folder, then puts a folder underneath it called conveyors then puts 4 folders in the conveyors folder with a number ) id like that to put four different parts in four different folders based on that how many priorities)
tried diving priorities but that wont work as i cant understand how to store an array to do what im asking
powershell
$salesorder = read-host -prompt 'What is the customer name and salesorder number? (ex.. turnkey - 3335)'
$jobnumber = read-host -prompt 'what is the Plant folder plus job number? (ex... 930-12345)'
$foldername = $jobnumber + " - " + $salesorder
#$conveyornumber = read-host -prompt "what is the number for conveyors? " + " - "
$priority = read-host -prompt "how many priorities are there?"
##************************* setting variables for second level basic Folder Structure *********************************
$partpath = '\\wal-file\public\sullivan\sully_temp_part.ipt'
$layout = 'D0100 - Layout'
$footprint = 'D0101 - Footprint'
$equipment = 'D01xx - Equipment'
$Guarding = 'D85xx - Guarding'
$conveyor = 'D60xx - Conveyors'
$platform = 'D90xx - Platforms'
#*************************** creating new variables based on folder name stylings *************************************
$workdir = new-item -path "C:\vault_workspace\Temp_vault\wendt\" -name $foldername -itemtype 'directory' -force
$layoutdir = new-item -path $workdir -name $layout -itemtype 'directory'
$layoutfilename = $layoutdir -join '.ipt'
#*************************** setting work directory input **************************************************************
new-item -path $layoutdir -name "$salesorder.ipt" -itemtype "file"
$footprintdir = new-item -path $workdir -name $footprint -itemtype 'directory'
$conveyordir = new-item -path $workdir -name $conveyor -itemtype 'directory'
#looping statement to create multiple folders
$conveyorinput = read-host -prompt "how many conveyors need to be made?"
for ($i = 1; $i -le $conveyorinput; $i++){"{0:D2}" -f $number} { [system.io.directory]::CreateDirectory("$conveyordir\D51$I")}
start-sleep -seconds 5
#creating multiple files
$conveyorarray = Get-ChildItem $conveyordir | Where-Object {$_.PSChildname} | Foreach-Object {$_.Name}
foreach ($path in $conveyorarray) {copy-item -path $partpath -destination "$conveyordir\$path\$jobnumber-4-$path-DUmmy-A0.ipt "}
i tried a few things all with mixed results no here close to what im looking to d. i tried goodling it but i couldnt figure out a way to implement anything close to what im asking some form of If statement would probably do it, but where would i put it and how would it work?
Thanks for any help

This is just a suggestion, can you look at adding functions so your code is readable. I can't see what you want. Can you also pepper it with output if you need to see what is going on Write-Host. I don't know what a sully sample is or how it is related to this so my guess is it's a folder or an ipt file? I can't read the code code-readability as it doesn't convey what you intend to to as far as I can tell beyond creating directories? If you can leave out the 'sully sample' language and use widget I think we could understand it better. Such as I need 4 Widget files for 4 people to look at?
# powershell
$salesorder = read-host -prompt 'What is the customer name and salesorder number? (ex.. turnkey - 3335)'
$jobnumber = read-host -prompt 'what is the Plant folder plus job number? (ex... 930-12345)'
$foldername = $jobnumber + " - " + $salesorder
#$conveyornumber = read-host -prompt "what is the number for conveyors? " + " - "
$priority = read-host -prompt "how many priorities are there?"
##************************* setting variables for second level basic Folder Structure *********************************
# Dunno what this file is or how it got here?
$partpath = '\\wal-file\public\sullivan\sully_temp_part.ipt'
$layout = 'D0100 - Layout'
$footprint = 'D0101 - Footprint'
$equipment = 'D01xx - Equipment' #Are these meant to be numbers or x character?
$Guarding = 'D85xx - Guarding'
$conveyor = 'D60xx - Conveyors'
$platform = 'D90xx - Platforms'
#*************************** creating new variables based on folder name stylings *************************************
$folderArray = #() # of things you want to keep track of
function CreateNewFolder() {
param(
$path = "C:\vault_workspace\Temp_vault\wendt\",
$name = $foldername,
[switch] $force
)
$newDirectory = new-item -path $path -name $name -itemtype 'directory' -force:$force
Write-Host "Adding $name to FolderArray"
$folderArray.Add($newDirectory)
return $newDirectory
}
$workdir = CreateNewFolder -path "C:\vault_workspace\Temp_vault\wendt\" -name $foldername -force
#$workdir = new-item -path "C:\vault_workspace\Temp_vault\wendt\" -name $foldername -itemtype 'directory' -force
$layoutdir = CreateNewFolder -path $workdir -name $layout
#$layoutdir = new-item -path $workdir -name $layout -itemtype 'directory'
$layoutfilename = $layoutdir -join '.ipt' # Why are we joining the directory to ipt?
#*************************** setting work directory input **************************************************************
new-item -path $layoutdir -name "$salesorder.ipt" -itemtype "file"
#$footprintdir = new-item -path $workdir -name $footprint -itemtype 'directory'
$footprintdir = CreateNewFolder -path $workdir -name $footprint
$conveyordir = new-item -path $workdir -name $conveyor -itemtype 'directory'
#looping statement to create multiple folders
$conveyorinput = read-host -prompt "how many conveyors need to be made?"
for ($i = 1; $i -le $conveyorinput; $i++){
# This just gets printed out?
"{0:D2}" -f $number
}
{
[system.io.directory]::CreateDirectory("$conveyordir\D51$I")
}
start-sleep -seconds 5
#creating multiple files
$conveyorarray = Get-ChildItem $conveyordir | Where-Object {
$_.PSChildname
} | Foreach-Object {
#{
Name = $_.Name
FullName = $_.FullName
}
}
foreach ($path in $conveyorarray) {
$name = $_.Name
$fullName = $_.Name
$destination = '{0}\{1}\{2}-4-{3}-Dummy-A0.ipt' -f $conveyordir, $name, $jobnumber, $path
copy-item -path $fullName -destination $destination # "$conveyordir\$path\$jobnumber-4-$path-DUmmy-A0.ipt "
}

so i actually changed the suyntax around completely but i was able to do the following
$salesorder = read-host -prompt 'What is the customer name and salesorder number? (ex.. turnkey - 3335)'
$jobnumber = read-host -prompt 'what is the Plant folder plus job number? (ex... 930-12345)'
$topleveldir = new-item -path "C:\vault_workspace\Temp_vault\wendt\" -name "M$jobnumber - $salesorder" -ItemType 'directory'
$subfolders = "D0100 - Layout", "D0101 - Footprint", "D01xx - Equipment","D85xx - Guarding", "D60xx - Conveyors", "D90xx - Platforms", "D09XX - Chutes"
foreach($subfolder in $subfolders){new-item -path "$topleveldir" -name $subfolder -type directory }
#$partpath = '\\wal-file\public\sullivan\sully_temp_part.ipt'
#p1
$p1conveyorinput = read-host -prompt "how many p1 conveyors need to be made?"
for ($i = 1; $i -le $p1conveyorinput; $i++) {
$p1c = "{0:D2}" -f $i
[system.io.directory]::CreateDirectory("$topleveldir\D60xx - Conveyors\D61$p1c-p1")
copy-item -path "\\wal-file\public\sullivan\sully_temp_part.ipt" -destination "$topleveldir\D60xx - Conveyors\D61$p1c-p1\D61$p1c-p1-dummy.ipt" -force
}
start-sleep -seconds 1
the only issue i run into is how to loop back into that last statement
#p1
$p1conveyorinput = read-host -prompt "how many p1 conveyors need to be made?"
for ($i = 1; $i -le $p1conveyorinput; $i++) {
$p1c = "{0:D2}" -f $i
[system.io.directory]::CreateDirectory("$topleveldir\D60xx - Conveyors\D61$p1c-p1")
copy-item -path "\\wal-file\public\sullivan\sully_temp_part.ipt" -destination "$topleveldir\D60xx - Conveyors\D61$p1c-p1\D61$p1c-p1-dummy.ipt" -force
}
start-sleep -seconds 1
for as many priorities there are without copying and changing the variables (which im going to do for now because it functions)

Related

Move files matching specific date from array of servers/folders to a local folder (Powershell)

I'm attempting to copy all files from an array of production servers that match a specific user-entered date (to prepare for rollbacks if necessary)...here is what I have tried:
[string[]]$ProdServerArray = "prdserver1", "prdserver2", "prdserver3"
[string[]]$InterfaceArray = "interfacefolder1", "interfacefolder2", "interfacefolder3", "interfacefolder4", "interfacefolder5"
New-Item -ItemType "directory" -Path "C:\GetFilesResults\$($date.toshortdatestring().replace("/","-"))\$search" -Force
$LocalPath = "C:\GetFilesResults\$($date.toshortdatestring().replace("/","-"))\$search"
do
{
$date = Read-host "Enter date (MM/DD/YYYY): "
}
while ($date -as [datetime] -isnot [datetime])
$date = $date -as [datetime]
$date
$search = foreach ($ProdServer in $ProdServerArray)
{
foreach ($Interface in $InterfaceArray)
{
'\\{0}\InterfaceFiles\{1}\' -f $ProdServer, $Interface
Get-ChildItem $search -File -Recurse | Where {$_.LastWriteTime -gt $date.date} | ForEach {
$actualSource = Split-Path $_.FullName
$actualDest = Split-Path $_.FullName.Replace($search,$LocalPath)
robocopy $actualSource $actualDest $_.Name /SEC }
}
}
I have been successful in getting the folder structure as I need it - "\prdserver1\InterfaceFiles\interfacefolder1\", but haven't been able to get the create/modify date of the files inside these folders and copy them to my local machine. I've attempted Copy-Item, robocopy, batch, etc., but haven't found a way to run a loop through all of these, and best case it seems to bomb out if it runs into a file or folder that doesn't match the criteria...worst case it does nothing.
While I wasn't able to fully test this, the for-each loop seemed to do it for me. The -Recurse paramater of Copy-Item seems to be the solution, along with a few other logic and syntax changes. Let me know if this solves your problem.
[string[]]$ProdServerArray = "prdserver1", "prdserver2", "prdserver3"
[string[]]$InterfaceArray = "interfacefolder1", "interfacefolder2", "interfacefolder3", "interfacefolder4", "interfacefolder5"
$LocalPath = New-Item -ItemType "directory" -Path "C:\GetFilesResults\$($date.toshortdatestring().replace("/","-"))\$search" -Force | select -Property FullName
do
{
$date = Read-host "Enter date (MM/DD/YYYY): "
}
while ($date -as [datetime] -isnot [datetime])
[datetime] $date = $date -as [datetime]
Write-Output $date
foreach ($ProdServer in $ProdServerArray)
{
foreach ($Interface in $InterfaceArray)
{
$search = '\\{0}\InterfaceFiles\{1}\' -f $ProdServer, $Interface
Get-ChildItem $search -File -Recurse | Where {$_.LastWriteTime -gt $date.date} |
ForEach {
$actualSource = Split-Path $_.FullName
$actualDest = Split-Path $_.Replace($search,$LocalPath)
Copy-Item -Path $actualSource -Destination $actualDest -Recurse
}
}

Manipulating Import-Csv objects and exporting to text file line by line

I'm basically trying to build a routine that reads a named folder directory, builds a CSV file, then reads in that CSV file, manipulates some of the properties to split data into new columns, exports that to another CSV.
This I have achieved with the following code:
$Folder = Read-Host 'Please enter a folder path'
$File = Read-Host 'Please enter a filename'
$OutputFile = $Folder + '\' + $File + '.csv'
$SplitFile = $Folder + '\' + $File + '_Split.csv'
$CopyDir = $Folder + '\WantedDocs\'
Get-ChildItem $Folder -Recurse -Include *.* |
select Directory, FullName, Name |
Export-Csv -Delimiter ',' -NoTypeInformation $OutputFile
$a = Import-Csv $OutputFile
$values = $a.Name.Split("_")
$a | Add-Member 'CliCode' -NotePropertyValue $values[3]
$a | Add-Member 'CopyDir' -NotePropertyValue $CopyDir
$a | Select Directory, FullName, Name, CliCode, CopyDir |
Export-Csv -Delimiter ',' -NoTypeInformation $SplitFile
Excuse me if my terminology isn't right, but I am now looking to build a batch file full of xcopy commands, using item values from the properties.
xcopy 'C:\Test\OriginalDocs\A\file1_A_A_12345678.txt' 'C:\Test\WantedDocs\*' /Y
When you use Import-Csv and assign it to a variable, that variable contain various properties, with each property containing an array of values taken from each line in the CSV file.
In my example the variable $a has properties called "Directory", "FullName" and "Name", the headers of the 3 columns in my CSV file.
If my CSV file contains these lines:
"Directory","FullName","Name"
"C:\Test\OriginalDocs\A","C:\Test\OriginalDocs\A\file1_A_A_12345678.txt","file1_A_A_12345678.txt"
"C:\Test\OriginalDocs\B","C:\Test\OriginalDocs\B\file2_B_B_43534554.txt","file1_B_B_43534554.txt"
The Directory property would be an array of 2 items: "C:\Test\OriginalDocs\A" and "C:\Test\OriginalDocs\B\"
The FullName property would be an array of 2 items: "C:\Test\OriginalDocs\A\file1_A_A_12345678.txt" and "C:\Test\OriginalDocs\B\file2_B_B_43534554.txt"
The Name property would be an array of 2 items: "file1_A_A_12345678.txt" and "file2_B_B_43534554.txt"
What I want to know is how would I be able to select all [0] items in the array for each property and build the xcopy command
e.g. if I do this:
$xc1 = "xcopy '"
$xc2 = $a.FullName
$xc3 = "' '"
$xc4 = $a.CopyDir
$xc5 = $a.CliCode
$xc6 = "\*' /Y"
$xcopy = $xc1 + $xc2 + $xc3 + $xc4 + $xc5+ $xc6
The resulting $xcopy variable contains all array vales
e.g. for the example above the xcopy variable ends up with the value:
xcopy 'C:\Test\OriginalDocs\A\file1_A_A_12345678.txt C:\Test\OriginalDocs\B\file2_B_B_43534554.txt' 'C:\Test\OriginalDocs\WantedDocs\ C:\Test\OriginalDocs\WantedDocs\12345678 43534554\*' /Y
What I want to achieve is to effectively do this with the [0] array values from each selected property:
$xc1 = "xcopy '"
$xc2 = $a.FullName[0]
$xc3 = "' '"
$xc4 = $a.CopyDir[0]
$xc5 = $a.CliCode[0]
$xc6 = "\*' /Y"
$xcopy = $xc1 + $xc2 + $xc3 + $xc4 + $xc5+ $xc6
Write the $xcopy variable to the text file (using Add-Content I believe)
Then do the same with the [1] array values:
$xc1 = "xcopy '"
$xc2 = $a.FullName[1]
$xc3 = "' '"
$xc4 = $a.CopyDir[1]
$xc5 = $a.CliCode[1]
$xc6 = "\*' /Y"
$xcopy = $xc1 + $xc2 + $xc3 + $xc4 + $xc5+ $xc6
And so on until all items in the arrays are dealt with.
So producing a text/batch file with a line for each item in the arrays i.e. all the [0], all the [1] etc.
Using my example above I'd get a text file like below.
xcopy 'C:\Test\OriginalDocs\A\file1_A_A_12345678.txt' 'C:\Test\OriginalDocs\WantedDocs\12345678\*' /Y
xcopy 'C:\Test\OriginalDocs\B\file2_B_B_43534554.txt' 'C:\Test\OriginalDocs\WantedDocs\43534554\*' /Y
I've been looking at foreach and ForEach-Object but so far I've not found anything that works for my needs. Maybe it can't be done?
To work line by line use foreach:
foreach ($Line in $a){ DoSomethingLikeCopy $Line.FullName to "$CopyDir\$($Line.CliCode)" }
Instead of XCopy use New-Item to create a new textfile with the Value of the old file or to create the folder for the new Item:
Get-Content -Path 'C:\Test\OriginalDocs\A\file1_A_A_12345678.txt' -raw | New-Item -Path 'C:\Test\OriginalDocs\WantedDocs\12345678\file1_A_A_12345678.txt' -Force
or
New-Item -Path'C:\Test\OriginalDocs\WantedDocs\12345678\*' -ItemType directory
It's pointless to export data to a CSV that you're reading back right away. Simply use a pipeline. Also, xcopy is an external command and can be run directly from PowerShell, so there's no need to have PowerShell create a batch file first.
This should be all you need:
$Folder = Read-Host 'Please enter a folder path'
Get-ChildItem $Folder -Recurse | ForEach-Object {
$clicode = $_.BaseName.Split("_")[-1]
& xcopy $_.FullName "${Folder}\WantedDocs\${clicode}\*" /y
}
If you indeed want output CSV files for every step of the way, you can do something like this:
# YOU NEED TO ADD CODE FOR CHECKING THE USER INPUT
# What I'm doing here is very rudimentary..
do {
$Folder = Read-Host 'Please enter a folder path'
} while (-not (Test-Path -Path $Folder -PathType Container))
$File = Read-Host 'Please enter a filename (no extension)'
# at the very least sanitize the given filename, and get only the Name without Extension
$BaseName = [System.IO.Path]::GetFileNameWithoutExtension($File)
$OutputFile = Join-Path -Path $Folder -ChildPath ($BaseName + '.csv')
$SplitFile = Join-Path -Path $Folder -ChildPath ($BaseName + '_Split.csv')
$CopyDir = Join-Path -Path $Folder -ChildPath 'WantedDocs'
# collect the files and get the properties Directory, FullName and Name
$a = Get-ChildItem $Folder -Recurse -Include *.* -File | Select-Object Directory,FullName,Name
# write the first CSV file:
$a | Export-Csv -Path $OutputFile -Delimiter ',' -NoTypeInformation
# redefine the collection to add extra properties CliCode, CopyDir and Result
$a = $a | Select-Object *,CliCode,CopyDir,Result
# loop through the collection
$a | ForEach-Object {
# the automatic variable $_ is a single object in the collection
# get the CliCode from the Name property:
# if the filename is "file1_A_A_12345678.txt", the CliCode will be "12345678"
if ($_.Name -match '([^_.]+)\..*$') {
$cliCode = $matches[1]
$targetDir = Join-Path -Path $CopyDir -ChildPath $cliCode
$_.CliCode = $cliCode # example: "12345678"
$_.CopyDir = $targetDir # example: "C:\Test\WantedDocs\12345678"
# copy the file, but create the target folder first if this does not exist
if (-not (Test-Path -Path $targetDir -PathType Container)) {
New-Item -Path $targetDir -ItemType Directory | Out-Null
}
Copy-Item -Path $_.FullName -Destination $targetDir
$_.Result = "OK"
}
else {
# show the error and add "Failure" to the result property
Write-Warning "Skipped file '$_.FullName'. Reason: CliCode not found"
$_.Result = "Failure"
}
}
# output the results of the copy as CSV file
$a | Export-Csv -Path $SplitFile -Delimiter ',' -NoTypeInformation
When done, the files are copied to the new locations and you'll have two CSV files:
The first 'Something.csv' before the copy:
"Directory","FullName","Name"
"D:\Test\OriginalDocs\A","D:\Test\OriginalDocs\A\file1_A_A_12345678.txt","file1_A_A_12345678.txt"
"D:\Test\OriginalDocs\B","D:\Test\OriginalDocs\B\file2_B_B_43534554.txt","file2_B_B_43534554.txt"
and the second 'Something_Split.csv' after the copy:
"Directory","FullName","Name","CliCode","CopyDir","Result"
"D:\Test\OriginalDocs\A","D:\Test\OriginalDocs\A\file1_A_A_12345678.txt","file1_A_A_12345678.txt","12345678","D:\Test\OriginalDocs\WantedDocs\12345678","OK"
"D:\Test\OriginalDocs\B","D:\Test\OriginalDocs\B\file2_B_B_43534554.txt","file2_B_B_43534554.txt","43534554","D:\Test\OriginalDocs\WantedDocs\43534554","OK"
The 'Result' column will display Failure if the filename did not contain a CliCode in the name, otherwise OK
Thank you for all the replies. Using a combination of what has been advised, I now have the solution I need.
Many thanks for all the assistance. I've added an if else section to the file processing because I would only be interested in files that follow a specific naming convention (xx_xx_xx_clicode_xxx.ext). This is for a specific project where I'll be supplied with 1000s of files, most of which should follow the naming convention. So I'm checking the number of elements in the $values variable array to make sure it has at least 4 values (i.e. [3] exists as a value). Where it doesn't exist I'm writing the filename out to a log file.
This is the completed solution:
do {
$Folder = Read-Host 'Please enter a folder path'
} while (-not (Test-Path -Path $Folder -PathType Container))
$File = Read-Host 'Please enter a filename (no extension)'
$OutputFile = Join-Path -Path $Folder -ChildPath ($File + '.csv')
$SplitFile = Join-Path -Path $Folder -ChildPath ($File + '_Split.csv')
$CopyDir = Join-Path $Folder -ChildPath 'WantedDocs'
$logfile = "log.txt"
$log = Join-Path -Path $Folder -ChildPath $logfile
Get-ChildItem $Folder -Recurse -Include *.* | select Directory,FullName,Name | Export-Csv -Delimiter ',' -NoTypeInformation $OutputFile
$a = Import-Csv $OutputFile
$a | Add-Member 'CopyDir' -NotePropertyValue $CopyDir
$a | Select Directory,FullName,Name,CopyDir | Export-Csv -Delimiter ',' -NoTypeInformation $SplitFile
Foreach ($Row in $a)
{
$values = $Row.Name.split("_")
If ($values.Count -gt 3)
{
$tempfile = Join-Path -Path $CopyDir -ChildPath $values[3]
$OriginalFile = $($Row.FullName)
$CopyFile = $tempfile
New-Item -ItemType directory -Path $tempfile -Force
Copy-Item $OriginalFile -Destination $CopyFile -Force -Recurse
}
Else
{
Add-Content $log $Row.Name
}
}
Write-Output "Finished"
Many thanks once again. Much appreciated.

Powershell File database comparison with drive letter variable input [duplicate]

This question already has an answer here:
Pass object[] into a function in PowerShell
(1 answer)
Closed 4 years ago.
I'm building a tool that will scan my files and a friend's files. We will use this to make sure we have the same files in our databases. The script I have so far has a variable input issue. For some reason, the PowerShell script fails on my drive letter input. Anyone have any ideas?
Here is my script:
{
function Show-Menu {
param (
[string] $Title = "Andy's Manual Database Tool"
)
Clear-Host
Write-Host ""
Write-Host "================ $Title ================"
Write-Host ""
Write-Host -f Green "1. Andys Files listing"
Write-Host -f green "2. Reids files listing"
Write-Host -f Red "3. Dark Matter Testing"
Write-Host "4. Convert .txt to .csv"
Write-Host "5. Convert Blank File to .csv"
Write-Host "6. Convert .csv to .txt"
}
Function Body {
Show-Menu
Write-Host ""
$Input = Read-Host "Please make a selection"
if ($Input -eq "1") {
Clear-Host
$root = Read-Host -Prompt 'Specify the location of Database? Example format: C:\*'
$y = read-host -Prompt 'Input file types. Format Example: " .jpg,.mp4,.mp3,.pdf .... " Do * for all'
$z = Read-Host -Prompt 'Your Save file name will be? Examples: Movies database , Music database , audiobooks.'
Get-ChildItem -Path $root -File -Recurse *.$y | Select-Object -Property Name | Export-Csv -NoTypeInformation $z Andy.csv
}
if ($Input -eq "2") {
Clear-Host
$root = Read-Host -Prompt 'Specify the location of Database? Example format: C:\*'
$y = read-host -Prompt 'Input file types. File Format Examples: " .jpg,.mp4,.mp3,.pdf .... " Do * for all'
$z = Read-Host -Prompt 'Your Save file name will be? Examples: Movies database , Music database , audiobooks.'
Get-ChildItem -Path $root -File -Recurse *.$y | Select-Object -Property Name | Export-Csv -NoTypeInformation $z' From Reid.csv'
}
if ($Input -eq "3") { Get-Process | Stop-Process }
if ($Input -eq "4") {
Clear-Host
Get-ChildItem *.txt | rename-item -newname { $_.name -replace ".txt",".csv" }
}
if ($Input -eq "5") {
Clear-Host
Get-ChildItem * -Exclude *.ps1,*.CSV,*.TXT | rename-item -newname { "$($_.name).CSV" }
}
if ($Input -eq "6") {
Clear-Host
Get-ChildItem *.csv | rename-item -newname { $_.name -replace ".csv",".txt" }
}
Write-Host 'Complete! ^_^'
Start-Sleep -seconds 5
Body
}
Body
}
This issue is here, from the script above:
$root = Read-Host -Prompt 'Specify the location of Database? Example format: C:\*'
$y = read-host -Prompt 'Input file types. Format Example: " .jpg,.mp4,.mp3,.pdf .... " Do * for all'
$z = Read-Host -Prompt 'Your Save file name will be? Examples: Movies database , Music database , audiobooks.'
Get-ChildItem -Path $root -File -Recurse *.$y |
Select-Object -Property Name |
Export-Csv -NoTypeInformation $z Andy.csv
I'm using $root as an input for my drive letter or location path which is the problem.
There a few minor issues.
$z Andy.csv Needs to be changed to "$z Andy.csv". You will notice when you ran this before you would of received the following message:
Export-Csv : Cannot bind parameter 'Delimiter'. Cannot convert value
"Andy.csv" to type "System.Char". Error: "String must be exactly one
character long."
Get-ChildItem -Path $root -File -Recurse *.$y Needs to be changed to Get-ChildItem -Path "$root" -Recurse -Include "*$y" - You are prompting the user to put in file extension with .<extension> (assigned to $y) then you are trying to filter with $y
Ex:$y = read-host -Prompt 'Input file types. Format Example: " .jpg,.mp4,.mp3,.pdf .... " Do * for all'
Issue: "*.$y" this would equal "..extension". Your results would then be 0 (unless you had a file with ..jpg or something like that)
Corrected:
if ($Input -eq "1") {
Clear-Host
$root = Read-Host -Prompt 'Specify the location of Database? Example format: C:\*'
$y = read-host -Prompt 'Input file types. Format Example: " .jpg,.mp4,.mp3,.pdf .... " Do * for all'
$z = Read-Host -Prompt 'Your Save file name will be? Examples: Movies database , Music database , audiobooks.'
Get-ChildItem -Path "$root" -Recurse -Include "*$y" | Select Name | Export-Csv -NoTypeInformation "$z Andy.csv"
}
You should be able to correct the rest of your script following the "Corrected" example.
EDIT:
Credit to TheIncredible1
There are automatic variables that should never be used other than for their intended purpose. In your case $Input:
Contains an enumerator that enumerates all input that is passed to a
function. The $input variable is available only to functions and
script blocks (which are unnamed functions). In the Process block of a
function, the $input variable enumerates the object that is currently
in the pipeline. When the Process block completes, there are no
objects left in the pipeline, so the $input variable enumerates an
empty collection. If the function does not have a Process block, then
in the End block, the $input variable enumerates the collection of all
input to the function.
However, in this case it should not effect your outcome. But, it is a very bad habit to get into and is best to be avoided.

Loop though network share and list all users folders and create/delete file

We have 1 main network share named the below, after the underscore there is 8 locations which are "abc$", "def$", "ghi$", "jkl$", "mno$", "pqr$", "stu$", "vwxyz$".
Depending on the users first letter in their username a folder is created with the which is the users home area.
Example username - AdamB will be put in Networkshare1_abc$.
Example 2 username - EdwardB will be put in Networkshare1_def$
Within this folder are the is a list of all users as a folder
Networkshare1_abc$
Networkshare1_def$
Networkshare1_ghi$
Networkshare1_jkl$
Networkshare1_mno$
Networkshare1_pqr$
Networkshare1_stu$
Networkshare1_vwxy$
I need a script that will
that will loop though only the top folder list the users
check to see if a text file exists and if it does delete it (have this working below)
$Wantedfile = "Networkshare1_stu$\user1\test.txt"
$timeStamp = (Get-Date -Format "dd-MM-yyyy-hh-mm")
$FileName = $timeStamp + ".txt"
if ((Test-Path $Wantedfile$FileName) -eq $false) {
Write-Host "file does not exists"
} elseif ((Test-Path $Wantedfile$FileName) -eq $true) {
Write-Host "file present..removing file"
Remove-Item $Wantedfile$FileName
}
The bit I am struggling with is the loop and how to get it to check each folder in the above locations as streamline as possible.
I am not sure if your files are really named like
"Networkshare1_stu$\user1\test.txt03-21-2017-19-41.txt"
but basically what you need is foreach loop. You need to get all the folders in the top folder. In $directories you will have abc$, def$ etc. folders. Then you will loop through each of them and search for the file using Where-Object.
$nameOfFile = "test.txt"
$fullPathFile = "\\Networkshare1_abc$\user1\test.txt"
$directories = Get-ChildItem "\\Networkshare1" -Directory
foreach($directory in $directories)
{
Write-Host "Searching in $directory.FullName ..."
$files = Get-ChildItem $directory -Recurse | Where-Object{$_.FullName -like "*$nameOfFile"}
# or to use fullPathFile
# $files = Get-ChildItem $directory -Recurse | Where-Object{$_.FullName -eq $fullPathFile}
foreach($file in $files)
{
Write-Host "Removing $file.FullName - continue?"
Read-Host ""
Remove-Item $file -Force
}
}

Debugging disk space cleanup script - Deleting files it should not be

I am working on a disk space script for our clients in my off time. I just tested it using the ISE, and it looks like it was working until I checked the transcript.
There are sections during the first removal cycle around line 32 where it is removing files in C:\Windows\System32\, which of course I didn't want it to. I am sure I did something wrong, but I have checked for typos, and I do not understand how it can get %system32% from a users directory.
If (([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([System.Security.Principal.WindowsBuiltInRole]::Administrator))
{
$Host.UI.RawUI.WindowTitle = $myInvocation.MyCommand.Definition + ' (Elevated)'
$Host.UI.RawUI.BackgroundColor = 'DarkBlue'
Clear-Host
}
Else
{
$newProcess = New-Object Diagnostics.ProcessStartInfo 'PowerShell'
$newProcess.Arguments = "& '" + $script:MyInvocation.MyCommand.Path + "'"
$newProcess.Verb = 'runas'
[Diagnostics.Process]::Start($newProcess) | Out-Null
exit
}
If ((Test-Path "C:\DiskSpaceCleanupLog\") -eq $False)
{
New-Item -ItemType Directory -Path "C:\DiskSpaceCleanupLog\"
}
$Date = [string]::Format( "{0:dd-MM-yyyy}", [datetime]::Now.Date )
$LogName = "C:\DiskSpaceCleanupLog\" + $Date + "Log.txt"
Start-Transcript $LogName
$Path = #()
$Array = #(Get-ChildItem C:\Users | Select-Object Name)
Read-Host -Verbose "Removing User Account temp files..."
Foreach ($Name IN $Array)
{
$Path = ("C:\Users\" + $Name.Name + "\AppData\Local\Temp\")
}
Foreach ($Path IN $Array)
{
Get-ChildItem | Remove-Item -Recurse -WhatIf
}
Remove-Variable Path
Read-Host -Verbose "Removing User Account crash dumps..."
Foreach ($Name IN $Array)
{
$Path = ("C:\Users\" + $Name.Name + "\AppData\Local\CrashDumps\")
}
Foreach ($Path IN $Array)
{
Get-ChildItem | Remove-Item -Recurse -WhatIf
}
Remove-Variable Path
Read-Host -Verbose "Removing User Account reporting files..."
Foreach ($Name IN $Array)
{
$Path = ("C:\Users\" + $Name.Name + "\AppData\Local\Microsoft\Windows\WER\ReportArchive\")
}
Foreach ($Temp IN $Path)
{
Get-ChildItem | Remove-Item -Recurse -WhatIf
}
Remove-Variable Path
Read-Host -Verbose "Removing User Account temp files from Internet Explorer..."
Foreach ($Name IN $Array)
{
$Path = ("C:\Users\" + $Name.Name + "\AppData\Local\Microsoft\Windows\Temporary Internet Files\")
}
Foreach ($Temp IN $Path)
{
Get-ChildItem | Remove-Item -Recurse -WhatIf
}
Read-Host -Verbose "Removing Recycle Bin files..."
Remove-Item -LiteralPath 'C:\$Recycle.Bin\' -Recurse -WhatIf
Read-Host -Verbose "Removing global crash dumps..."
Remove-Item "C:\ProgramData\Microsoft\Windows\WER\ReportQueue" -Recurse -WhatIf
Remove-Item "C:\ProgramData\Microsoft\Windows\WER\ReportArchive" -Recurse -WhatIf
Read-Host -Verbose "Removing Windows Update cached files..."
Stop-Service -DisplayName 'Windows Update'
Remove-Item "C:\Windows\SoftwareDistribution\Download\*" -Recurse -WhatIf
Start-Service -DisplayName 'Windows Update'
Remove-Variable Array, Path
Read-Host -Verbose "Cleaning base image of update cache..."
DISM.exe /Online /Cleanup-Image /SPSuperseded
Read-Host -Verbose "Running Windows Clean Manager..."
$OSVersion = Get-WMIObject -Class Win32_OperatingSystem | Format-Table Version
If ($OSVersion -le 6.1)
{
cleanmgr.exe /verylowdisk
}
Read-Host -Verbose "Removal is complete. Sending logs..."
Stop-Transcript
$SecurePassword = ConvertTo-SecureString "InsertPasswordHere" -AsPlainText -Force
$emailcredential = New-Object System.Management.Automation.PSCredential ("email#domain.com", $SecurePassword)
Send-MailMessage -To "Name Here <email#domain.com>" -From "Name Here <email#domain.com>" -Subject ("Disk Space Cleanup Log - " + $Date) -Body "Attached is the log from the script." -Attachments $LogName -SmtpServer "smtp.office365.com" -Credential $emailcredential -UseSSL -Port "587" -DeliveryNotificationOption OnFailure
Line 32 is Get-ChildItem | Remove-Item -Recurse -WhatIf
The are several things that should be adjusted in your code but the issue that is befalling you now is that you have not specified a -Path. Therefore Get-ChildItem will be returning items from the working directory!
Get-ChildItem | Remove-Item -Recurse -WhatIf
Should be instead
Get-ChildItem $path | Remove-Item -Recurse -WhatIf
Like I said though there are several potential pitfalls and areas of improvement there to be addressed. You use the same loop 5 times. A couple are exactly the same.
I believe the issue is on line 23, where the code is not populating the array with full pathnames. See Get full path of the files in PowerShell for some advice on how to get the full pathnames instead.

Resources