I put together a Robocopy script to backup data, but the problem I am having is the script is reading the parent folder and trying to execute the robocopy filters and error out.
what I would like for it to do is indent one and start copying the subfolder and use the filter there. the file structure is
Users\tim jones, sam adams
I just want the tim jones folder and the sam adams user folders with the Robocopy filter added to it. any help is welcomed
$Comp = Read-Host 'Please enter a computer name or IP'
do{
If (Test-Connection $Comp -quiet -Count 1) {
Write-host 'The host responded' -ForegroundColor "yellow"
Read-Host 'Press any key to continue...' | Out-Null
$ping = "ture"
Clear-Host
Get-WmiObject -ComputerName $Comp -class Win32_NetworkLoginProfile | Select- Object Name,#{label='LastLogon';expression={$_.ConvertToDateTime($_.LastLogon)}}
New-Item -Path \\skyzone\t$\sky\ -ItemType directory
$SourcePath = "\\$Comp\C$\Users\";
$TargetPath = "\\skyzone\t$\sky";
#Users libraries
$PicturesLibrary = ("\Pictures");
$Downloads = ("\Downloads");
$Favorites = ("\Favorites");
$Documents = ("\Documents");
$Desktop = ("\Desktop");
$Video = ("\Videos");
#User Outlook files and logs
$Outlook = ("\AppData\Local\Microsoft\Outlook")
$argsFromFolders = ("$SourcePath\$PicturesLibrary","$SourcePath\$Downloads","$SourcePath\$Favorites","$SourcePath\$Documents","$SourcePath\$Desktop","$SourcePath\$Video" ,"$SourcePath\$Outlook");
$argsToFolders = ("$TargetPath\Pictures","$TargetPath\Downloads","$TargetPath\Favorites","$TargetPath\Documents","$TargetPath\Desktop","$TargetPath\Videos","$TargetPath\Outlook");
For ($i=0; $i -lt $argsFromFolders.Length; $i++) {
Write-Host -ForegroundColor Green "Processing" $argsFromFolders[$i] "To" $argsToFolders[$i];
robocopy $argsFromFolders[$i] $argsToFolders[$i] *.* /MT:16 /XJ *.pst /R:3 /W:1 /NP /e /xf *.vmdk *.vmem *.iso *.exe *.ost desktop.ini /tee /Log+:
}
Your question is unclear and the sample is incomplete. You refer to $user which is never created and there are no robocopy-calls here. Because of this I can't give you a complete solution.
Take a look at this example source-path in your code:
$SourcePath = "\\localhost\C$\Users\";
$PicturesLibrary = ("\Pictures");
"$SourcePath\$PicturesLibrary"
#Output
\\localhost\C$\Users\\\Pictures
There are too many backslashes in the spot where you joined the two strings. Remove them from the variables or use Join-Path
$SourcePath = "\\localhost\C$\Users\"
$PicturesLibrary = "\Pictures"
Join-Path $SourcePath $PicturesLibrary
#Output
\\localhost\C$\Users\Pictures
Or
$SourcePath = "\\localhost\C$\Users"
$PicturesLibrary = "Pictures"
"$SourcePath\$PicturesLibrary"
#Output
\\localhost\C$\Users\Pictures
The username is missing. You need to use Get-Childitem on the $sourcePath to get the list of users in the first place and loop through those.
Sample:
$SourcePath = "\\localhost\C$\Users\"
Get-ChildItem -Path $SourcePath |
#Get folders only... And exlude public?
Where-Object { $_.PSIsContainer -and $_.Name -ne 'Public' } |
ForEach-Object {
#Code to run for each user-folder
$PicturesLibrary = ("Pictures")
Join-Path $_.FullName $PicturesLibrary
}
\\localhost\C$\Users\Default.migrated\Pictures
\\localhost\C$\Users\defaultuser0\Pictures
\\localhost\C$\Users\frode\Pictures
Update: Try something like this (untested).
$Comp = Read-Host 'Please enter a computer name or IP'
If (Test-Connection $Comp -quiet -Count 1) {
Write-host 'The host responded' -ForegroundColor "yellow"
Read-Host 'Press any key to continue...' | Out-Null
Clear-Host
Get-WmiObject -ComputerName $Comp -class Win32_NetworkLoginProfile | Select- Object Name,#{label='LastLogon';expression={$_.ConvertToDateTime($_.LastLogon)}}
$TargetPath = '\\skyzone\t$\sky'
if(-not (Test-Path -Path $TargetPath -PathType Container)) { New-Item -Path $TargetPath -ItemType Directory | Out-Null }
$Folderlist = ("Pictures","Downloads","Favorites","Documents","Desktop","Videos","Outlook");
Get-ChildItem -Path "\\$Comp\C$\Users\" |
#Get folders only... And exclude public?
Where-Object { $_.PSIsContainer -and $_.Name -ne 'Public' } |
ForEach-Object {
$user = $_.Name
foreach ($folder in $Folderlist) {
$from = Join-Path $_.FullName $folder
$to = Join-Path $TargetPath "$user\$folder"
Write-Host -ForegroundColor Green "Processing '$from' To '$to'"
robocopy $from $to *.* /MT:16 /XJ *.pst /R:3 /W:1 /NP /e /xf *.vmdk *.vmem *.iso *.exe *.ost desktop.ini /tee /Log+:\\apgrwkate1090f\t$\dren\$user\backup.txt
}
}
}
Related
With this code I get the data but is not reflected on the txt file. I just get a bunch of Microsoft.PowerShell.Commands.Internal.Format.FormatStartData.
Microsoft.PowerShell.Commands.Internal.Format.GroupStartData
Microsoft.PowerShell.Commands.Internal.Format.FormatEntryData
Instead the names of each file.
Here is the code:
param(
[string]$foldername = 'unknown'
)
if (Test-Path $foldername){
$location = Join-Path -Path $HOME -ChildPath "files.txt"
$files = Get-ChildItem $foldername | Where-Object {$_.PsIsContainer -ne $True} | Format-Table
Name
$amount = Get-ChildItem $foldername | Where-Object {$_.PsIsContainer -ne $True} | Measure-
Object
Add-Content -Path $location -Value $files
Write-Host $amount.count "filenames were written to file" $location
}
else {Write-Host "Sorry,", $foldername, "does not exist."
break
}
First get-childitem supports the switch File, no need to pipe and filter. The Format-Table is used to format the output displayed on the screen, so as you want to write to a file you do not need it.
Also only use break within a loop, if you want to stop the processing use return instead.
param(
[string]$foldername = 'unknown'
)
if (Test-Path $foldername){
$location = Join-Path -Path $HOME -ChildPath "files.txt"
#gets all files in the specified path
$files = Get-ChildItem $foldername -File
#counts the number of files
$amount = $files.count
#If you want the fullpath in the logfile use $files.fullname if you only want the name use $files.name
$files.FullName | Add-Content -Path $location
Write-Host "$amount filenames were written to file $location"
}
else {
Write-Host "Sorry, $foldername, does not exist."
return
}
I'm an Network Engineer an I wrote a small but effective PS Script to search logs(or any file for that matter) for textpatterns. Now this script only outputs the line, filename and so on. Now I wanted to extend the script so that when it finds a line, it'll tell me the line, filename and so on but also the contents of that line.
So it should look like this:
LineNumber Filename Path Pattern
---------- -------- ---- -------
4 190719_Success.log C:\skripte\190719_Success.log test
Text that's on Line 4 of the .log should appear here
5 190719_Success.log C:\skripte\190719_Success.log test
Text thats on Line 5 of the .log should appear here
Sorry for the formatting, I hope you get what I mean.
Since I'm relatively new to PS Scripting Im kinda lost how I should achieve this goal or if thats even possible.
Here is my code sofar:
Clear-Host
$Pfad = Read-Host "Bitte Pfad angeben" #Enter Directory Path to Search
$Suchbegriff = Read-Host "Suchbegriff eingeben" #Enter Pattern to search for
New-Item -ItemType directory -Path C:\Skripte -erroraction 'silentlycontinue' #create C:\Skripte Folder
Remove-Item -Path C:\Skripte\Suchergebnis.txt -erroraction 'silentlycontinue' #Cleanup from previous run
Remove-Item -Path C:\Skripte\Indizierung.csv -erroraction 'silentlycontinue' #Cleanup
cd $Pfad
echo $file.fullname
echo ""
select-string -Path .\*.* -Pattern "$Suchbegriff" -erroraction 'silentlycontinue' | Select-Object LineNumber,Filename,Path,Pattern | ft -wrap #Search the specified Directory
echo ""
while(($Create = Read-Host -Prompt "Unterordner durchsuchen? J für Ja, N für Nein") -ne "x") #Userinput if Subdirectorys should be searched aswell
{
switch ($Create)
{
'J'
{
Get-Childitem -erroraction 'silentlycontinue' | Get-ChildItem -Recurse -erroraction 'silentlycontinue' | Where-Object {$_.PSIsContainer} | Export-CSV -NoClobber -NoTypeInformation -Path C:\Skripte\Indizierung.csv #Get all Subdirectorys and put them in a CSV, two GCI are needed to reliably get all subdirectories.
$Files = import-csv -Delimiter ',' -Path C:\Skripte\Indizierung.csv #Import CSV
foreach ($File in $Files)
{
cd $file.fullname
echo $file.fullname
echo ""
select-string -Path .\*.* -Pattern "$Suchbegriff" -erroraction 'silentlycontinue' | Select-Object LineNumber,Filename,Path,Pattern | ft -wrap
echo ""
pause
exit
}
}
'n'
{
pause
Exit
}
}
}
Take a look at the following code. I added a loop for processing the files and some validation for the input + your request for the displaying the line content to the console.
Code adapted (#Theo: thanks for input)
#Get input
[System.String]$SearchPath = Read-Host -Prompt 'Enter path'
[System.String]$SearchPattern = Read-Host -Prompt 'Enter search pattern'
[System.String]$SearchRecurse = Read-Host -Prompt 'Search recurse (Y/N)'
#Validate input
if ((-not $SearchPath) -or (-not (Test-Path -Path $SearchPath)))
{
throw ('Path "' + $SearchPath + 'is not available!')
}
if ((-not $SearchPattern))
{
throw ('Search pattern is empty!')
}
if (('Y', 'N') -notcontains $SearchRecurse)
{
throw ('Search recurse parameter "' + $SearchRecurse + ' is not valid!')
}
#Get all files
Out-Host -InputObject 'Get all files...'
[PSCustomObject[]]$Files = #()
if ($SearchRecurse -eq 'Y')
{
$Files = Get-ChildItem -Path $SearchPath -File -Recurse -Force #Collect also files from subfolders
}
else
{
$Files = Get-ChildItem -Path $SearchPath -File -Force #Collect only files from the current folder
}
#Search for string
Out-Host -InputObject 'Search for string...'
[PSCustomObject[]]$Output = #()
foreach ($File in ($Files)) #Process each file
{
Out-Host -InputObject $File.FullName
$Output += Select-String -Path $File.FullName -Pattern $SearchPattern | Select-Object -Property LineNumber, Filename, Path, Pattern, Line
}
$Output | Format-Table -Wrap
Im currently trying to get a script to do the following:
search a file location and obtain any .txt,.ini,.config file.
filter this file on an input from the user.
move all the files to a location.
Im having a problem trying to feed in the variable and its probably really simple but im currently struggling to figure out what I need to do without splitting the string up manually. any ideas?
$QQ = Read-Host -Prompt "String your searching for:"
$QL = Read-Host -Prompt "Enter the file location you wish to search:"
$FT = Get-ChildItem -Path "$QL" -recurse | where {$_.extension -eq ".txt"} | % {$_.fullname}
$FI = Get-ChildItem -Path "$QL" -recurse | where {$_.extension -eq ".ini"} | % {$_.fullname}
$FC = Get-ChildItem -Path "$QL" -recurse | where {$_.extension -eq ".config"} | % {$_.fullname}
$FTS = Get-Content -Path "$FT" -Filter "$QQ"
$FIS = Get-Content -Path "$FI" -Filter "$QQ"
$FCS = Get-Content -Path "$FC" -Filter "$QQ"
$FD = "C:\Search-$QQ"
$FD1 = Get-ChildItem $FD
function folder {
if ($FD -eq $Null) {New-Item "$FD" -ItemType directory}}
function search{
if ($FTS -ne $null){Copy-Item -Path $ft -Destination "$fd" | Write-Host "$FT" | Format-List}
if ($FIS -ne $null){Copy-Item -path $fi -Destination "$fd" | Write-Host "$FI" | Format-List}
if ($FCS -ne $null){Copy-Item -Path $fc -destination "$fd" | Write-Host "$FC" | Format-List}
}
folder
search;
An example of the error being received is: (obviously an issue with it treating the multiple files in the string as one)
Get-Content : Cannot find path 'C:\test\Test\1c.config C:\test\Test\2c.config C:\test\Test\3c.config' because it does not exist.
right off the bat I see the folder function will not work property as $FD will never be null since you assign a string to it, if you need to check if the folder exists use Test-Path. but in relation to your actual script the problem is your use of get-content which is trying to read all of your files contents into an array of strings. from the looks of it you should just be working with the arrays returned by Get-ChildItem and use Test-Path to check your paths rather than that weird Get-Content method you are using(since the content of the files doesn't matter, just whether they exist or not). You also need to incorporate a loop to act on each array element individually rather than trying to work on them in groups like you are.
(This Script is to mass search application files to find values like server id's or passwords hardcoded etc)
Fixed code:
$QQ = Read-Host -Prompt "String your searching for:"
$QL = Read-Host -Prompt "Enter the file location you wish to search:"
$FT = Get-ChildItem -Path "$QL" -recurse | where {$_.extension -eq ".txt"} | % {$_.fullname}
$FI = Get-ChildItem -Path "$QL" -recurse | where {$_.extension -eq ".ini"} | % {$_.fullname}
$FC = Get-ChildItem -Path "$QL" -recurse | where {$_.extension -eq ".config"} | % {$_.fullname}
$FTS = Get-Content -Path $FT -Filter "$QQ"
$FIS = Get-Content -Path $FI -Filter "$QQ"
$FCS = Get-Content -Path $FC -Filter "$QQ"
$FD = "C:\Support\Search-$QQ"
$FD1 = Test-Path $FD
function folder {
if ($FD1 -eq $false) {New-Item "$FD" -ItemType directory}
}
function search{
if ($FTS -ne $null){Copy-Item -Path $ft -Destination "$fd" | Write-Host "$FT" | Format-List}
if ($FIS -ne $null){Copy-Item -path $fi -Destination "$fd" | Write-Host "$FI" | Format-List}
if ($FCS -ne $null){Copy-Item -Path $fc -destination "$fd" | Write-Host "$FC" | Format-List}
}
folder
search;
try this
$QL = Read-Host -Prompt "Enter the file location you wish to search:"
if (-not (Test-Path $QL))
{
write-host "Specified path ($QL) doesnt exists "
return;
}
$QQ = Read-Host -Prompt "String your searching for:"
$FD = "C:\Search-$QQ"
New-Item "C:\Search-$QQ" -ItemType directory -Force | out-null
Get-ChildItem -Path "$QL" -recurse -include "*.txt", "*.ini", "*.config" |
select-string -Pattern "$QQ" -SimpleMatch |
%{ Copy-Item -Path $_.Path -Destination "$fd" -Force ; $_.Path }
I'm writing a script to delete pdf files older than 6 months in folder with the 'Email' prefix.
However, my second dir command within my foreach never runs, its code is blocked.
$Now = Get-Date;
$DaysTillDelete = "180";
$LastWrite = $Now.AddDays(-$DaysTillDelete);
$TargetFolder = "C:\Test EMDATA\EMDATA\";
$BackupPath = "\\SHPFS02\IT\EmPower Old";
$EmailFolders = #();
if(-Not(Test-Path -path ($TargetFolder + "\OldFiles" ))) {
mkdir -p ($TargetFolder +"\OldFiles");
}
$Network = Test-Path $BackupPath
#New-PSDrive -Name O -PSProvider FileSystem -Root "$BackupPath"; #-Credential $cred
Write-Host "Running Script"
dir $TargetFolder | %{
# Only delete files with the Email prefix
$name = $_.Name;
if ($_.Name.Length -le 5) {return;}
$id = $_.Name.SubString(0,5);
if ($id -eq "Email")
{
Write-Host "Found slip folder"
$EmailFolders += $TargetFolder + $_;
}
}
ForEach ($folder in $EmailFolders)
{
Write-Host $folder;
dir -path $folder -include *.pdf | %{
Write-Host "Checking" $name;
# Only select files older than 6 months
if( $_.LastWriteTime -le "$LastWrite")
{
$activeItem = Get-Item $TargetFolder + $_;
#Move files into oldfiles
Write-Host $TargetFolder
move-item -path $activeItem -destination ($TargetFolder + "OldFiles\");
if ($Network)
{
move-item -path $activeItem -destination "O:\";
}
Write-Host $_;
remove-item $activeItem;
Write-Host "Deleting" + $name;
}
}
}
The script works till line 31 but doesn't continue on past line 32 and being a fairly beginner PS user I can't see why.
Only use -include with the -recurse parameter.
http://technet.microsoft.com/en-us/library/hh849800.aspx
The Include parameter is effective only when the command includes the
Recurse parameter or the path leads to the contents of a directory,
such as C:\Windows*, where the wildcard character specifies the
contents of the C:\Windows directory.
What you want instead is the -filter parameter:
dir -path $folder -filter *.pdf
I am new to powershell and am running into a problem while trying to exclude certain directories during recursive copy. Any help is appreciated!
Thanks in advance.
$Date = Get-Date
$Date = $Date.adddays(-1)
$destPath = "\\destination\test"
$srcPath = "H:\program files\symphony\Save"
$srcPathRemits = “H:\program files\symphony\files"
$destDrive = "X:"
$User = "user"
$Password = "password"
$exclude = #('H:\program files\symphony\files\Temp\*','H:\program files\symphony\files\Other\*','H:\program files\symphony\files\etc\*','H:\program files\symphony\files\ParsedXML\*')
$net = new-object -ComObject WScript.Network
$net.MapNetworkDrive($destDrive, $destPath, $false, $User, $Password)
gci -recurse -path $srcPathRemits -Exclude $exclude | ? {!($_.psiscontainer) -AND $_.lastwritetime -gt $Date} | % { write-host $_.fullname; Copy-Item -path $_.fullname -destination $destDrive}
$net.RemoveNetworkDrive($destDrive,"true","true")
You didn't say what the problem was, but I'll assume that the directories ($exclude) were not properly excluded. Try this instead, for the gci line:
Get-Item -Path H:\program files\symphony\files\* -Exclude Temp, Other, etc, ParsedXML | Get-ChildItem -recurse | ? {!($_.psiscontainer) -AND $_.lastwritetime -gt $Date} | % { write-host $_.fullname; Copy-Item -path $_.fullname -destination $destDrive}