I am new to PowerShell and have an issue. I need a PowerShell script to modify the first line of a .dat file within a zip folder. Then the zip folder will be need to be renamed but the file within has to keep the same name.
Any help will be appreciated!
I have the following code. It is reading the latest zip file from one directory and copying it into a new worker2 directory. This is working fine. I am trying to open the file and modify the first line. However the file is blank so the code is not copying into the file.
$today = get-date -Format yyyyMMdd
robocopy "C:\Tcc_Touchpoints\Tcc_Touchpoints\data\fusion\Worker\"
"C:\Tcc_Touchpoints\Tcc_Touchpoints\data\fusion\Worker2\" /s
/maxage:$today
$file = gci C:\Tcc_Touchpoints\Tcc_Touchpoints\data\fusion\Worker2\ | sort
LastWriteTime | select -last 1
$file2 = "C:\Tcc_Touchpoints\Tcc_Touchpoints\data\fusion\Worker2\" + $file
$zipfileName = $file2
$fileToEdit = "Worker.dat"
$path = $zipfileName + '\' + $fileToEdit
$contents = Get-Content $fileToEdit #-path $path
$contents
Add-Type -assembly System.IO.Compression.FileSystem
$zip = [System.IO.Compression.ZipFile]::Open($zipfileName,"Update")
#$zip = [System.IO.Compression.ZipFile]::Open($path,"Update")
$robotsFile = $zip.Entries.Where({$_.name -eq $fileToEdit})
$desiredFile = [System.IO.StreamWriter]($robotsFile).Open()
$desiredFile.BaseStream.SetLength(0)
$desiredFile -replace 'SET PURGE_FUTURE_CHANGES Y','SET
PURGE_FUTURE_CHANGES N'
$desiredFile.Write($contents)
$desiredFile.Flush()
$desiredFile.Close()
# Write the changes and close the zip file
$zip.Dispose()
Write-Host "zip file updated"
Your code is not far off. The following edits a single plain text entry in a ZIP file in-place.
Be sure to use the correct text encoding (i.e. the encoding your Worker.dat actually is in). Not specifying the encoding when working with text files will lead to mangled data at some point, always play it safe there.
using namespace System.Text
using namespace System.IO
using namespace System.IO.Compression
Add-Type -Assembly System.IO.Compression.FileSystem
$fileToEdit = "Worker.dat"
$fileEncoding = [Encoding]::UTF8
$zipFileName = "C:\path\to\your\file.zip"
$zip = [ZipFile]::Open($zipfileName, "Update")
$entry = $zip.Entries.Where({$_.name -eq $fileToEdit}) | Select-Object -First 1
$reader = [StreamReader]::new($entry.Open(), $fileEncoding)
$currentText = $reader.ReadToEnd()
$reader.Dispose()
$newText = $currentText -replace "\}$"," }"
$writer = [StreamWriter]::new($entry.Open(), $fileEncoding)
$writer.Write($newText)
$writer.Dispose()
$zip.Dispose()
This does not set the last modified date of the ZIP entry. You can (propably) do this by setting a new value to the $entry.LastWriteTime property.
Related
Sorry i am newbie. i only know how to copy/move/delete files using powershell. it will be really helpful if someone can help me in this matter and please excuse my english.
I have multiple sub folders, lets say
C:\test\1
C:\test\2
C:\test\3
inside the folder there is multiple image files. i want to list the sub folder's file name and size and save text files inside the subfolders.
C:\test\1\filelist.txt
C:\test\2\filelist.txt
C:\test\3\filelist.txt
filelist.txt will have something like this
Image1.png 30kb
Image2.png 4MB
Here is a sample script i found from online but i need it to save text file in subfolders based on subfolder file names.
$Folder = 'C:\pic'
$Output = 'C:\output.txt'
$Files = Get-ChildItem -Path $Folder -Filter *.png -File
$objShell = New-Object -ComObject Shell.Application
$objFolder = $objShell.Namespace($Folder)
foreach( $File in $Files ) {
$objFile = $objFolder.ParseName($File)
$Name = $objFolder.GetDetailsOf($objFile, 0)
$Size = $objFolder.GetDetailsOf($objFile, 1)
$Length = $objFolder.GetDetailsOf($objFile, 27)
$Tab = [char]9
"$Name$Tab$Size$Tab$Length" | Out-File -Append -FilePath $Output
}
```
If you want to use a built application for this, I recommend:
https://www.karenware.com/powertools/karens-directory-printer
For over 800 files I need information that's in the file name to be included in the contents of the text file (actually .md files).
The file names are always of the same structure, something like 0000-title-text-1-23.md; only the 1-23 part changes (and that is the information I need).
I am a novice as it comes to scripting, but I figured out that this should be an easy task for PowerShell — yet I don't get it working the way I want. What did come closest:
Get-Childitem "C:\PATH\*.md" | ForEach-Object{
$fileName = $_.BaseName
Add-Content -Path .\*.md -Value $fileName
}
But that adds all file names in the directory, not just the one from the file itself.
What am I doing wrong?
Use this code to do what you exactly want,
it will get the last 2 parts of your filename and
put it in the beginning of your file content.
Get-Childitem "C:\PATH\*.md" | ForEach-Object{
$fileNameParts = ($_.BaseName).split('-')
$info = $fileNameParts[-2] + '-' + $fileNameParts[-1]
$info + (Get-Content $_ -Raw) | Set-Content $_
}
Something like this would work although it does add the content to the end of the file:
#Get all the .txt or .md files in your location
Get-ChildItem -Filter "*.txt" | Foreach-Object{
#Get the base name of the file
$baseName = $_.BaseName
#Split the base name
$array = $baseName -Split '-'
#Put the third and fourth element in the array into a separate variable
#This will be added to the file
$addToFile = $array[3] + '-' + $array[4]
#Add the $addToFile variable to the file
Add-Content $_.FullName -Value $addToFile
}
I need to pull logs from the original path in C:\ to log directory in D:\Logs but everytime the original path create new log, the script need to append new lines, not replace or rewrite the whole lines.
I already tried this but i guess this replace the whole file and I'm not sure about the Param things.
$SourceFolder = "C:\ProgramData\Sophos\Sophos Anti-Virus\logs"
$DestinationFolder = "D:\Logs\SophosAntivirus"
Function ChangeTabToSpace
{
Param(
[string] $OldFile = "",
[string] $NewFile = ""
)
$OldText = (Get-Content $OldFile -Raw)
#Change all tabt \t to space
$NewText = ($OldText -replace "`t"," ")
#Delete the last empty line
if ($NewText.Length -ge 2) {
$NewText = $NewText.Substring(0,$NewText.Length-2)
}
if (!(Test-path "$NewFile")) {
New-Item -type file "$NewFile" -force | Out-Null
}
#Write-Output $NewText | Out-File -Encoding utf8 "$NewFile"
[System.IO.File]::WriteAllLines($NewFile, $NewText)
}
If its a simple text file you can use the following
"the string you want or have" | out-file -path $path -append
This will add the string to a new line at the end of the file.
You don't need to pipe the input in like I did... its just how I learned to use it and just kept using it.
I have a "ZIP" file and when we extract this, we have 1 "EXE" file within 4-5 sub folder depth level.
I would like to grab that "EXE" file and copy into another folder. How to do it using PowerShell?
I tried below, but it will copy all the ZIP content,
$shell = New-Object -ComObject shell.application
$zip = $shell.NameSpace("Source Path")
foreach ($item in $zip.items()) {
$shell.Namespace("Destination Path").CopyHere($item)
}
Simple snippet should get your job done
#Sets the variable to the Source folder, recurse drills down to folders within
$Source = get-childitem "C:\Users" -recurse #"C:\Users" an example
#Filters by extension .exe
$List = $Source | where {$_.extension -eq ".exe"}
#Copies all the items to the specified destination
$List | Copy-Item -Destination "C:\Scripts" #"C:\Scripts" an example
The module above scans for every single .EXE files within C:\Users* and copies them to C:\Scripts
As it stands, Clint's answer did not work for me, but something based on Extract Specific Files from ZIP Archive does, with a variation to target a specifically named file. Will need a further tweak to handle multiple files sharing the same name.
Code:
# Set source zip path, target output directory and file name filter
$ZipPath = 'C:\temp\Test.zip'
$OutDir = 'C:\temp'
$Filter = 'MyExe.exe'
# Load compression methods
Add-Type -AssemblyName System.IO.Compression.FileSystem
# Open zip file for reading
$Zip = [System.IO.Compression.ZipFile]::OpenRead($Path)
# Copy selected items to the target directory
$Zip.Entries |
Where-Object { $_.FullName -eq $Filter } |
ForEach-Object {
# Extract the selected items from the zip archive
# and copy them to the out folder
$FileName = $_.Name
[System.IO.Compression.ZipFileExtensions]::ExtractToFile($_, "$OutDir\$FileName", $true)
}
# Close zip file
$Zip.Dispose()
I currently have a script that will loop through a group of files in a folder - open each one up and let me enter a new file name and then rename it. I am then trying to create a CSV file with the old name in one column and the new name of the file in the second column.
#[void][Reflection.Assembly]::LoadWithPartialName('Microsoft.VisualBasic')
Add-Type -AssemblyName Microsoft.VisualBasic
$folderpath = 'C:\Scans\docs\' '#
$items = Get-ChildItem -Recurse $folderpath *.pdf
$newFileName = ""
$counterID = 0
$amountOfScans = $items.Length
foreach( $i in $items) {
Start-Process ((Resolve-Path ("$folderpath$i")).Path)
Start-Sleep -Seconds 1
$counterID++
$newFileName = [Microsoft.VisualBasic.Interaction]::InputBox("Enter the new file name $counterID / $amountOfScans :", $i)
Stop-Process -Name "Acro*"
Add-Content -Path 'C:\Scans\fileNames.csv' -Value "$i","$newFileName "
Rename-Item $i.FullName ("$newName.pdf")
}
This does work but it outputs into the csv only in the first column like:
old file name 1
new file name 1
old file name 2
new file name 2
How do make this output:
old file name 1 | new file name 1
old file name 2 | new file name 2
You're passing an array. A CSV is nothing more than a text file, so you want to pass the entire line as a single string.
Add-Content -Path 'C:\Scans\fileNames.csv' -Value "`"$i`",`"$newFileName`""