How can I separate my content on powershell? - powershell

This is my code: It runs correctly but it prints my content together. I was told to use the Write-ouput command and write an empty string but its not coming out right. Does anyone have any suggestions
$file1='/Users/raelynsade/Documents/cpt180stuff/pets/dogs/dognames.txt'
$file2='/Users/raelynsade/Documents/cpt180stuff/pets/cats/catnames.txt'
$fileExist = (Test-Path -Path $file1) -AND (Test-Path -Path $file2)
if ($fileExist -eq $True) {
$file_content = Get-Content -Path $file1
Write-output -InputObject $file_content
$file_content = Get-Content -Path $file2
Write-output -InputObject $file_content
Add-Content -Path "/Users/raelynsade/Documents/cpt180stuff/pets/cats/catnames.txt"
-Value "Sammy"
Add-Content -Path "/Users/raelynsade/Documents/cpt180stuff/pets/cats/catnames.txt"
-Value "Luna"
Get-Content -Path "/Users/raelynsade/Documents/cpt180stuff/pets/cats/catnames.txt" } else {
Write-output -Inputobject "Unable to access one or more files" }

If you put powershell's implicit output to work for you and enclose it all in a subexpression $(...) then you can combine all the lines as you desire and output once. Add the -Passthru parameter of Set-Content and you don't need to read the file again after writing.
$file1='/Users/raelynsade/Documents/cpt180stuff/pets/dogs/dognames.txt'
$file2='/Users/raelynsade/Documents/cpt180stuff/pets/cats/catnames.txt'
$fileExist = (Test-Path -Path $file1) -AND (Test-Path -Path $file2)
if ($fileExist -eq $True){
$(Get-Content -Path $file1
""
Get-Content -Path $file2
"Sammy"
"Luna") | Set-Content -Path "/Users/raelynsade/Documents/cpt180stuff/pets/cats/catnames.txt" -PassThru
} else {
"Unable to access one or more files"
}

something like this?
$file1='/Users/raelynsade/Documents/cpt180stuff/pets/dogs/dognames.txt'
$file2='/Users/raelynsade/Documents/cpt180stuff/pets/cats/catnames.txt'
$fileExist = (Test-Path -Path $file1) -AND (Test-Path -Path $file2)
if ($fileExist)
{
#content to dog file
Get-Content -Path $file1
" "
#content to cat file with new values added
Add-Content -Path $file2 -Value "Sammy" ,"Luna"
Get-Content -Path $file2
}
else
{
"Unable to access one or more files"
}

Related

For loop with list not working as expected Powershell

I'm trying to create a powershell script which checks a log file for lines of text and if the line exists restarts a service and resets/archives the log. I got it working before with 1 "checkstring" if you will, but I've been struggling to get it to work with a list of strings. Could anyone help me figure out where I'm going wrong?
This is the code I'm currently using:
$serviceName = "MySQL80"
$file = "test.txt"
$pwd = "C:\tmp\"
$checkStrings = New-Object System.Collections.ArrayList
# Add amount of checkstrings
$checkStrings.add("Unhandled error. Error message: Error retrieving response.")
$checkStrings.add("Unhandled error. Error message: Error retrieving response. Second")
$logName = "ServiceCheck.log"
$backupFolder = "Archive"
$logString = (Get-Date).ToString("ddMMyyyyHHmmss"), " - The service has been reset and the log moved to backup" -Join ""
Set-Location -Path $pwd
if(Test-Path -Path $file) {
if(Test-Path -Path $backupFolder) {
} else {
New-Item -Path $pwd -Name $backupFolder -ItemType "director"
}
foreach ($element in $checkStrings) {
$containsWord = $fileContent | %{$_ -match $element}
if ($containsWord -contains $true) {
Restart-Service -Name $serviceName
$backupPath = $pwd, "\", $backupFolder, "\", $date, ".log" -join ""
$currentFile = $pwd, "\", $file -join ""
Copy-Item $currentFile -Destination $backupPath
Get-Content $currentFile | select-string -pattern $checkString -notmatch | Out-File $currentFile
if(Test-Path -Path $logName) {
Add-Content $logName $logString
} else {
$logString | Out-File -FilePath $logName
}
}
}
}

How can I get Powershell to generate logs after moving files?

Hi this is the first time I create a program using powershell, I created a powershell script to move old files that are not in use to a NAS, the code works as what I want, but I need a Log.txt file for find out what files have been moved. can someone please help me?
$Date = Get-Date -UFormat %d-%m-%Y
$Source = 'C:\Source\'
$Temp = 'C:\Backup-Temp\'
$Nas = 'D:\Destination\'
$Ext = "*.zip","*.rar"
$SetTime = '-5'
New-Item -Path $Temp -Name "Backup-$Date" -ItemType "directory"
Foreach ($Ext in $Ext) {
get-childitem -Path "$Source" -Recurse |
Where-object {$_.LastWriteTime -lt (get-date).AddDays($SetTime) -and $_.name -like "$Ext"} |
Move-item -destination "$Temp\Backup-$Date" |
Compress-Archive -Path "$Temp\Backup-$Date" -DestinationPath "$Nas\Backup-$date.Zip"
}
$Date = Get-Date -UFormat %d-%m-%Y
$Source = 'C:\Source\'
$Temp = 'C:\Backup-Temp\'
$Nas = 'D:\Destination\'
$Ext = "*.zip","*.rar"
$SetTime = '-5'
$LogFileFullName = 'c:\tmp\log.txt'
function Write-Log([string]$msg){
Out-File -FilePath $LogFileFullName -InputObject "$([DateTime]::Now): $msg" -Append
}
New-Item -Path $Temp -Name "Backup-$Date" -ItemType "directory"
Foreach ($Ext in $Ext) {
get-childitem -Path "$Source" -Recurse |
Where-object {$_.LastWriteTime -lt (get-date).AddDays($SetTime) -and $_.name -like "$Ext"} |
ForEach-Object {
Move-item $_.FullName -destination "$Temp\Backup-$Date" |
Compress-Archive -Path "$Temp\Backup-$Date" -DestinationPath "$Nas\Backup-$date.Zip"
Write-Log $_.FullName
}
}
You could just add the following to your chain of piped commands:
Add-Content $logfile "$_.name`n"
where $logfile is set to a static filename prior.
I may be old-fashioned, but having so many commands in one chain is prone to failure. It would be more resilient to break-up the chain so that you can include some error checking along the way.
A better but less desirable option would be to put your chain within a try/catch block.
Best of luck.

Why doesn't this create a file on the destination server?

I recently did a storage migration and we had about 700 files that failed to migrate out of around 7 million (we need to purge some files, I know). I wrote the script below that is supposed to look at the corresponding file on the destination, compare the date values and if the file doesn't exist or has an older date, it's supposed to copy it over. Unfortunately, it's not copying it over. I don't get any errors but the file doesn't land on the destination. What am I doing wrong?
Also, I originally tried to grab the entire directory but it choked on the volume of files so that's why it parses each directory in turn instead.
$toplvl = "D:\Users\"
$folders = Get-ChildItem -Path $toplvl -Directory
$file = ""
$folders | ForEach-Object {
$original = $_.FullName
$dest = $_.FullName.Replace("D:","\\NewFileServer\D$")
$OutputFile = $_.FullName.Replace($toplvl,"D:\filelist-")
$FirstFind=0 #used to create a header in the output file
# Get all files under $original, filter out directories
$filelist = Get-ChildItem -Recurse $original | Where-Object { -not $_.PsIsContainer }
Write-Host $original #write directories to host to track progress
$filelist | ForEach-Object {
## Check if the file (from $original) exists with the same path in $dest
If (Test-Path ($_.FullName.Replace($original,$dest) ) ) {
## the file from $original has a match in $dest
$file = Get-Childitem -Path $_.FullName.Replace($original,$dest)
If ($_.LastWriteTime -gt $file.LastWriteTime) {
## file from $original is newer than $dest
If ( -Not ($FirstFind)) {Add-Content -Path $OutputFile -Value "Original File, Date"}
$FirstFind = 1
Add-Content -Path $OutputFile -Value $_.FullName -NoNewline
Add-Content -Path $OutputFile -Value "," -NoNewline
Add-Content -Path $OutputFile -Value $_.LastWriteTime
Copy-Item -Path $_.FullName -Destination $file.FullName
}
else {
## file from $original is same or older than $dest; can remove else statement
}
}
else {
## the file from $original is missing from $dest
If ( -Not ($FirstFind)) {Add-Content -Path $OutputFile -Value "Original File, Date"}
$FirstFind = 1
Add-Content -Path $OutputFile -Value $_.FullName -NoNewline
Add-Content -Path $OutputFile -Value "," -NoNewline
Add-Content -Path $OutputFile -Value $_.LastWriteTime
Copy-Item -Path $_.FullName -Destination $_.FullName.Replace($original,$dest)
}
}
}
Hopefully I didn't mess this up copying it over - it's my first time posting and I'm still figuring out the formatting.

Logging file output

The logging only traps on the IDs in my text file (get-content) it does not print the file name which gets copied
I've tried using the log option with robocopy however it only logs the last enter in my get-content text file
$Source = "F:\Temp\"
$Test = "F:\Output\"
$Daily_Results="F:\Output\Test\"
foreach ($ID in Get-Content F:\Files\files.txt) {
$ID
Get-ChildItem -Path $Source | foreach {
if($_ -match $ID) {
$Path=$Source+"$_\"
$Path
robocopy $path $test
Write-Host $Path
"File copied"
Write-Output $ID "File copied" | Out-File $Daily_Results\$(get-date -f yyyy-MM-dd)_CopyMove_Results.txt -append
Write-Output $_ | Out-File $Daily_Results\$(get-date -f yyyy-MM-dd)_CopyMove_Results.txt -append
}
}
}
What happens is that $_ gets you the full object, you need to explicitly say you want the Name.
Write-Output $_.Name | Out-File $Daily_Results\$(get-date -f yyyy-MM-dd)_CopyMove_Results.txt -append
As you are copying the files one-by-one, I see no real advantage in using robocopy here, but rather user PowerShell's own Copy-Item cmdlet.
Because you didn't say what the $ID from the text file could be, from the code you gave I gather that it is some string that must be part of the file name to copy.
This should work for you then
$Source = 'F:\Temp'
$Destination = 'F:\Output'
$Daily_Results = Join-Path -Path 'F:\Output\Test' -ChildPath ('{0:yyyy-MM-dd}_CopyMove_Results.txt' -f (Get-Date))
foreach ($ID in Get-Content F:\Files\files.txt) {
Get-ChildItem -Path $Source -File -Recurse | Where-Object { $_.Name -like "*$ID*" } | ForEach-Object {
$_ | Copy-Item -Destination $Destination -Force
Write-Host "File '$($_.Name)' copied"
# output to the log file
"$ID File copied: '$($_.Name)'" | Out-File -FilePath $Daily_Results -Append
}
}

PowerShell Move-Item $filename

I searched, i googled.. about to smash my head on the table
how come this will not work?
move-Item $path$file $targetdir
it gives me an error
Move-Item : An object at the specified path C:\Repository\test.csv
does not exist.
now if i debug this and i output using
write-output move-Item $path$file $targetdir
and take that output and paste it (file name with path and destination) it works!
and trust me the file is there. =\
Code below
$path = 'C:\test\'
$TimeStamp = Get-Date -Format "MM-dd-yyyy_hh-mm-ss"
$LogFile = Get-Date -Format "MM_dd_yyyy"
$targetdir = "C:\test\Uploaded\"
#Get-ChildItem -path $path\* -Include *.csv | foreach-object {$_.Fullname} | Format-Table name -hidetableheaders | Out-File $path\list.txt
Get-ChildItem -path $path\* -Include *.csv | Format-Table name -hidetableheaders | Out-File $path\list2.txt
get-content C:\test\list2.txt | where {$_ -ne ""} | out-file C:\test\list.txt
Remove-Item C:\test\list2.txt
$list = get-content C:\test\list.txt
foreach ($file in $list)
{
$ftp = "ftp://REMOVED/$file"
"ftp url: $ftp"
$webclient = New-Object System.Net.WebClient
$uri = New-Object System.Uri($ftp)
"Uploading $file..."
$succeeded = $true;
& {
trap { $script:succeeded = $false; continue }
$webclient.UploadFile($uri, $path+$file)
}
if ($succeeded)
{
echo $file 'Was successfully uploaded!' $Timestamp >> logfile$LogFile.log
move-Item -path $path$file -destination $targetdir
#test-path $path$file
}
else
{
echo $file 'Was not successfully uploaded, will retry later' $Timestamp >> logfile$LogFile.log
}
}
exit
Basics are:
Test-Path before you move it (file and destination)
Move the file, ensure you have permission (force it to move)
so:
echo $targetdir
echo "$path$file"
if (!(Test-Path $targetdir)) {
New-Item -ItemType directory $targetdir
}
if(Test-Path "$path$file") {
Move-Item "$path$file" $targetdir -Force
} else {
echo "file does not exist"
}
If you loop over a collection you have to use the ".FullName" property of the object:
Get-ChildItem $path | ForEach-Object { Move-Item $_.FullName $targetdir -Force }
Does the target directory already exist? I believe Move-Item will fail if the target directory doesn't exist. If that's the case, you can simply test for existence of the directory beforehand and then create as necessary.
If (!(Test-Path -Path $targetdir)) {
New-Item -ItemType directory -Path $targetdir
}
This worked for me. Thank you #TheMadTechnician. Hopes this helps everyone
$TimeStamp = Get-Date -Format "MM-dd-yyyy_hh-mm-ss"
$LogFile = Get-Date -Format "MM_dd_yyyy"
$path='C:\test\'
$targetDir = 'C:\test\Uploaded\'
$fileList = Get-ChildItem $path*.csv
If(!(Test-Path $TargetDir)){New-Item -ItemType Directory -Path $TargetDir|Out-Null}
$fileList | Select -ExpandProperty Name | Out-File 'C:\test\list.txt'
$list = get-content C:\test\list.txt
foreach ($file in $list)
{
$ftp = "ftp://REMOVED/$file"
"ftp url: $ftp"
$webclient = New-Object System.Net.WebClient
$uri = New-Object System.Uri($ftp)
"Uploading $file..."
$succeeded = $true;
& {
trap { $script:succeeded = $false; continue }
$webclient.UploadFile($uri, $path+$file)
}
if ($succeeded)
{
echo $file 'Was successfully uploaded!' $Timestamp >> logfile$LogFile.log
move-Item -path $path$file -destination $targetdir$Timestamp"_"$file
#test-path $path$file
}
else
{
echo $file 'Was not successfully uploaded, will retry later' $Timestamp >> logfile$LogFile.log
}
}
exit
How about this then:
ForEach($File in $List){
Join-Path $path $file | Move-Item -Dest $Targetdir
}
Edit: Also... your creation of list.txt, it bothered me so I had to comment. Format-Table should be used for formatting text, not for selecting a value to output to a file. There's a better way to do that, consider this alternative:
Get-ChildItem "$path*.csv" | Select -ExpandProperty Name | Out-File $pathlist.txt
Since you say that $path = 'C:\test\' you are adding extra backslashes in there that may cause issues for some commands.
Edit2: Ok, if that doesn't work, why not work with the files themselves instead of outputting to a file, importing from that file, and then working with things.
$path='c:\test\'
$TargetDir = 'c:\test\NewDir'
$FileList = Get-ChildItem $path*.csv
If(!(Test-Path $TargetDir)){New-Item -ItemType Directory -Path $TargetDir|Out-Null}
$FileList | Move-Item -Destination $TargetDir
Then if you really want a list of those file names just pipe $FileList to Select and then to Out-File
$FileList | Select -ExpandProperty Name | Out-File 'C:\Test\list.txt'
Here, look through this and see if there's anything you like. I made a few changes, such as declaring paths at the beginning for everything, I moved the WebClient object creation outside of the loop, and changed how things are displayed on screen. Plus I skip the entire exporting to text file and re-importing it.
$path = 'C:\test'
$ftpaddr = 'ftp://ftp.example.com/uploads'
$TimeStamp = Get-Date -Format "MM/dd/yyyy hh:mm:ss tt"
$LogFile = Get-Date -Format "MM_dd_yyyy"
$LogDir = "C:\Test\Logs"
If(!(test-path $LogDir)){New-Item -ItemType Directory -Path $LogDir | Out-Null}
$targetdir = 'C:\test\Uploaded'
If(!(test-path $targetdir)){New-Item -ItemType Directory -Path $targetdir | Out-Null}
$list = Get-ChildItem -path $path\* -Include *.csv
$webclient = New-Object System.Net.WebClient
"ftp url: $ftpaddr"
foreach ($file in ($list|select -ExpandProperty Name))
{
$uri = New-Object System.Uri(("$ftpaddr/$file"))
Write-Host "Uploading $file... " -NoNewline -ForegroundColor White
$succeeded = $true
& {
trap { $script:succeeded = $false; continue }
$webclient.UploadFile($uri, "$Path\$file")
}
if ($succeeded)
{
Write-Host "Success!" -ForegroundColor Green
"$Timestamp`t$File was successfully uploaded!" | Out-File "$logdir\logfile$LogFile.log" -Append
move-Item -path "$path\$file" -destination $targetdir
}
else
{
Write-Host "Failed! Will retry later." -ForegroundColor Red
"$Timestamp`t$File was not successfully uploaded, will retry later" | Out-File "$logdir\logfile$LogFile.log" -Append
}
}