I have a bunch of .txt files with various names in a folder, and I need to merge them into a single file that can be read in Office Word or LibreOffice Writer.
The tricky part is, the pasted files should be organized by creation date, have a title put before the content and a page break at the end, like this
Title of older file
File content
Page break
Title of newer file
File content
Page break
I could do this with Java, but it seems a little overkill. It would be nice if this could be done using Windows Powershell, or Unix bash. Added newlines should be Window style, though.
Full disclaimer: I know something about Bash, little about the Powershell and almost nothing about .doc/.odf formats.
Merging TXTs into one DOCX and adding page breaks (PowerShell, requires MS Word):
[Ref]$rSaveFormat = "Microsoft.Office.Interop.Word.WdSaveFormat" -as [Type]
$oWord = New-Object -ComObject Word.Application
$oWord.Visible = $false
$sPath = <path to dir with txt files>
$cInFiles = Get-ChildItem $sPath
$sOutFile = $sPath + "\outfile.docx"
$iWordPageBreak = 7
$iNewLineChar = 11
$oDoc = $oWord.Documents.Add()
$oWordSel = $oWord.Selection
foreach ($sInFile in $cInFiles) {
$sInFileTxt = Get-Content $sInFile
$oWordSel.TypeText($sInFile)
$oWordSel.TypeText([Char]$iNewLineChar)
$oWordSel.TypeText($sInFileTxt)
$oWordSel.InsertBreak($iWordPageBreak)
}
$oDoc.SaveAs($sOutFile, $rSaveFormat::wdFormatDocumentDefault)
$oDoc.Close()
$oWord.Quit()
$oWord = $null
For explanations see this blog post on TechNet.
Edit: without Word you probably should use ODT format and directly edit content.xml. Example in Python. Though personally I would simply concatenate the TXT files. Unless you have a million of them it's faster and easier to add page breaks manually than actually edit XML.
Related
I downloaded a backup folder of about 3,000 files from our email service provider. None of the files have an associated filetype; instead the file extension was appended to the name of each individual file. For example:
community-involvement-photo-1-jpg
social-responsibility-31-2012-png
report-02-12-15-pdf
I can manually change the last dash to a period and the files work just fine. I'm wondering if there is a way to batch convert all of the files so they can be sorted and organized properly. I know in the Command Line I can do something like ren *. *.jpg but there are several different file types contained in the folder, so it wouldn't work for all of them. Is there any way I can tell it to convert the last "-" in each file name into a "." ?
I'm on Windows 10; unable to install any filename conversion programs unless I want to go through weeks of trouble with the IT group.
$ordner = "c:\temp\pseudodaten"
$Liste = (get-childitem -path $Ordner).Name
cd $ordner
foreach ($Datei in $Liste) {
$Length = $datei.length
$NeuerName=$Datei.Substring(0,$Length-4)+"."+$datei.Substring($Length - 3, 3)
rename-item -Path $Datei -NewName $NeuerName
}
I want to see all the files in a folder and its sub folders and list its encoding.
I know that you can use git ls-files to see the files and file* to get the name + its encoding.
But I need help how I can do both at the same time.
The reason is that we have problem with encoding and need to see what files are encoded in what way. So I guess a PS script would work fine as well.
I think the best way to solve this by Powershell is first get your files by following Script:
$folder = Get-ChildItem -Path "YourPath"
and in a foreach ($file in $folder) use one of the following scripts to get the encoding (which is straightforward)
https://www.powershellgallery.com/packages/PSTemplatizer/1.0.20/Content/Functions%5CGet-FileEncoding.ps1
https://vertigion.com/2015/02/04/powershell-get-fileencoding/
What I'm trying to accomplish:
Create a PS script to run from a single Admin machine, but search against C$ on all Windows servers in AD.
Search for a specific list of paths\filenames that I provide.
If ANY of the specific list of paths\filenames are found on a server, THEN output the server name, and paths\filenames to a *.CSV file titled "Badfiles.csv" on the Admin machine.
Was trying to build from the following syntax but admittedly my old brain is not good at this stuff, and I've only specified a single file here - how do I refer to a list of multiple paths\files? Thank you for helping an old lady out. :)
$name= gc env:computername
$computers= get-content -path C:\Windows\Temp\v.bat
$csvfile = "c:\temp\$badfiles.csv"
foreach ($computer in $computers) {
"\$computer\C$\" | Get-ChildItem -recurse -filter "*.bat"
}
To refer to a list of items whether those are files or computer names you will need to use what is called an Array.
You can create an array in many ways, in your case it might best to create a list in a txt file and afterwards in Powershell you read the list contents using get-content, save the result in a variable and it will automatically be saved as an array!
Then iterate through each of them using what is called a foreach loop, that basically lets you take each of the items in the array and do something with it, then move to the next item and so on until every item has been dealt with.
Now the most important part of what you want to achieve is not clear. Let me explain.
To check if a file exists you can use test-path. That will return true or false and you can then act upon the result of that. You need to define an exact path and name of a file to check for this to work.
If you don't know the exact names and paths of files that need to be checked, you can use Get-ChildItem similarly as you have done in the code you provided. The caveat here is that you have to narrow down the scope of the file search as much as you can. In your example you search for the .bat file extension on the whole machine and that can result in some issues. A typical C drive will have hundreds of thousands if not millions of files and folders. Parsing all of them can take a long time.
So this is an important distinction to understand and what causes confusion for me is that you say in "2. Search for a specific list of paths\filenames that I provide..." yet in the code you use Get-ChildItem to get all files instead of providing a list of filenames.
Further I will assume you have a list of filenames with exact known paths.
Now in your given code I can see you have found some of the right commands but they need to be arranged differently to produce the results you need.
Please review this example code that might help you further:
Example ComputerList.txt file content(list of computer hostnames to check):
computer1
serverXYZ
laptop123
Example FileList.txt file content(List of files to check for in each of the above computers):
c:\temp\virus.bat
c:\games\game.exe
c:\Pictures\personal.jpg
Now the PowerShell code:
# Gets the list of items from TXT files and saves them as arrays in variables
$ComputerNames = Get-Content 'c:\temp\ComputerList.txt'
$FileList = Get-Content 'c:\temp\FileList.txt'
# Define the path and name of CSV report
$BadFiles = "c:\temp\badfiles.csv"
# Define the foreach loop that will iterate through each hostname in computer list
foreach($computer in $ComputerNames){
# Define foreach loop that will iterate through each file in the list and test their path in the current computer in the current iteration
foreach($file in $FileList){
# Test the path of the current file in the loop and append the CSV file if it was found
# Convert the file path to C$ share path
$file = $file -replace("c:","c$")
# Define path of file to test
$FileToTest = "\\$computer\$file"
if (test-path $FileToTest -ErrorAction SilentlyContinue){
# This block will run only when a bad file has been found
# This part can be tricky but it is used to make sure we properly format the current bad file entry when we append it to the resulting CSV file
$BadFile = "" | select Computer,File
# Save information about current computer
$BadFile.computer = $computer
# Save information about current file
$BadFile.file = $file
# Append the entry to an array of found bad files
$BadFileList += $badfile
}
}
}
# When done iterating through every computer and file, save the results in a CSV file
$BadFileList | ConvertTo-Csv -NoTypeInformation | Out-File $BadFiles
The above is a full code snippet you can test and run in your environment. First please create the two TXT files and make sure you run PowerShell with the appropriate permissions to access the C$ network shares of the servers.
The snippet should work but I have not tested it myself. Let me know if there are any errors.
Please test and feel free to ask if you have any follow up questions.
Good day,
I am trying to rename/organize files based on the match/lookup found in the text file.
I have a couple of hundred Cyrillic(Russian) named media files in a folder like this:
файл 35.avi
файл34.avi
файл2 4.avi
файл14.avi
*note that some files have spaces
The text file, with the desired names, looks like this:
файл 35.avi| 4. файл 35.avi
файл34.avi| 3. файл34.avi
файл2 4.avi| 1. файл2 4.avi
файл14.avi| 2. файл14.avi
The reason it looks that way (with | as a separator) is because I tried using "Bulk Renaming Utility" which uses pipe | as a separator for "Rename Pairs" function. So essentially, the filename to the right of pipe | is the final product. Unfortunately, that function does not work with Cyrillic(Russian) or other non standard characters.
I found PowerShell script HERE which appears to be almost what I need except that it does not match file names before renaming.
Similarly, I found this Python script HERE which does what i need but it's for Ubuntu. Unfortunately, I am on a Windows7 and not sure it applies to me.
Any recommendations?
Thank you very much for your time!
You could read the text file into a hashtable, where the key is the old name (the value on the left hand side of the |), and the value is the new name:
$RenameTable = #{}
Get-Content textfile.txt |ForEach-Object {
$OldName,$NewName = $_.Split('|')
$RenameTable[$OldName] = $NewName
}
Then rename the files based on what is in the hashtable:
Get-ChildItem .\folder\with\avi\files |Rename-Item -NewName {
if($RenameTable.ContainsKey($_.Name)){
$RenameTable[$_.Name]
} else {
$_.Name
}
}
Given a SSRS report definition file with an embedded image in it, just wondering if its possible to extract that image XML to recreate the original image file.
e.g. :
inside the rdlc file, you might see xml like this :
<EmbeddedImage Name="tick">
<MIMEType>image/bmp</MIMEType>
<ImageData>Qk1mAwAAAAAAADYAAAAoAAAAEAAAABEAAAABABgA ... <<REST OF IMAGE HERE>>
</ImageData>
</EmbeddedImage>
Is it possible to take the ImageData, and transform form it in some way to re-create the original image bitmap byte stream ?
(This might be useful in cases such as when you've lost the original image file on which the embedded image was based.)
Two approaches are detailed in this blog post:
Copy the encoded image from one report to another if you need to reuse it there.
Export a copy of the report to Excel and copy the image from the spreadsheet.
Or if you need access to the image more directly, I found this utility that will parse the XML and load and export the images. Looks like source code is available.
I have created a small Power Shell script to solve this problem:
$ErrorActionPreference = 'Stop';
Get-ChildItem -Filter '*.rdl' | ForEach {
$reportFile = $_;
Write-Host $reportFile;
$report = [xml](Get-Content $reportFile);
$report.Report.EmbeddedImages.EmbeddedImage | Foreach {
$imagexml = $_;
$imageextension = $imagexml.MIMEType.Split('/')[1];
$filename = $imagexml.Name + '.' + $imageextension;
Write-Host '->' $filename;
$imageContent = [System.Convert]::FromBase64String($imagexml.ImageData);
Set-Content -Path $filename -Encoding Byte -Value $imageContent;
}
}
https://gist.github.com/Fabian-Schmidt/71746e8e1dbdf9db9278
This script extracts all images from all reports in the current folder.
Open the XML (in notepad++ or anything)
Look for the <ImageData></ImageData> tags
Copy the 64-bit encoded string between the tags
Find a utility to convert x64 encoded strings to files. I used this website and downloaded the image
I just needed to do this and realised that it is possible to cut and paste the embedded image, even though it is not possible to copy and paste.