I am trying to write a powershell script which will return the contents inside a txt file. However, I do not want to specify the drive of the txt file as the txt file will be placed in the same folder as the powershell script.
I am using this line of code:
get-content .\document.txt | select -first 1 -skip 1
but it doesnt work.
Inside document.txt:
This is the first line
This is the second line
What script do I write to retrieve the second line "This is the second line" without having to put the full path like "C:\Data\Scripts\Document.txt"? I have searched online solution but many solutions required me having to put its destination path.
get-content $PSScriptRoot\document.txt | select -first 1 -skip 1
Note that $PSScriptRoot will only have a value when the script is executing, but it will represent the path of where the script resides.
I may not understand question correctly but you can display the content of the text file by
cat <yourfile.name>
if you want to get the part of the text file you can do
cat <yourfile.name> | Select-String '<text you want to get>'
you can refer to this site on how to manipulate the output https://msdn.microsoft.com/en-us/powershell/reference/5.1/microsoft.powershell.utility/select-string
and if ever you want to run the script in Bash you need different script if ever
If you are looking for the second line then use the below:
By default, each line will be an index of an array. So the second line will be having the index as 1
(get-content .\document.txt)[1]
TO find the text file have a look at this link
PowerShell: current directory relative to executing script
After you get that ,We can move to second line of the file easily,
Solution here:-to print the required line
The code may convert itself to be something like this
#include this is in your script,this part of the code will get the absolute path of the script from whereever its running
function Get-ScriptDirectory
{
$Invocation = (Get-Variable MyInvocation -Scope 1).Value
Split-Path $Invocation.MyCommand.Path
}
$path = Join-Path (Get-ScriptDirectory) 'Your Script Name'
$path.ToString()
$path =$path.Substring(0,$path.IndexOf('Your Script Name'))
$path
#now $path has the directory in which you have your files,append it with your text file name
(Get-content $path+'textfilename.txt')[1]
#and get the second line of the content
Credits to SomeShinyobjects
This can be simply written as
$path=$PSScriptRoot+'\textfilename.txt'
(Get-content $path)[1]
Related
So I have the below script for a project at work:
# This script will look for a CSV in the script folder
# If found it will split the CSV based on a change in a column header
# It will then create seperate CSV files based on the column data
# get script directory and add it to a variable
Set-Location $PSScriptRoot
$baseDir = $PSScriptRoot
# get a list of csv file names
$csvfile = Get-ChildItem -Path $baseDir -Filter *.csv
# If multiple CSV files loop through all of them
foreach ($i in $csvfile) {
# Import and split the original csv
# Change the value after -Property to match the column header name of the column used to split on value change -
# Header names with spaces require surrounding quotes -
# This value will also be used to name the resulting CSV file
Import-Csv $i | Group-Object -Property "Submission ID" |
Foreach-Object {$path="Output\"+$_.name+".csv" ; $_.group |
Export-Csv -Path $path -NoTypeInformation}
# get the current time and date
$procdte = Get-Date -uformat "%m-%d-%Y %H %M %S"
# rename the original file so that it's not processed again
Rename-Item $i -NewName "Processed $procdte.txt"
}
# End processing loop
Important: some parts of this script are commented out - like the Rename-Item line is half-commented. Dunno why, think it's a stackoverflow markdown issue. It isn't like that in ISE
I tested it out with two csv files in the current directory. It's supposed to rename both files at the end to a .txt so they don't get processed again. When I just run the script, it misses the 2nd csv file. But when I step through it with debugger in ISE, it renames both files fine. What gives?
Ran powershell script, expecting both CSV files to be renamed, however it only renamed one of them. Thought there was an issue with the script, but when I run it in debug, it renames both files fine. Have managed to replicate multiple times.
Edit: to specify - this is not designed to work with two csv files specifically. It's supposed to work with one or more. I was just using two to test.
I'm trying to create a file listing of a folder for a secure file transfer tool. This is what I do:
Get-ChildItem c:\files | % {$_.FullName} > c:\temp\list1.csv
$csv = Import-Csv C:\TEMP\list1.csv -Header Path
The output holds every file in a new line, but I need it in one line.
Required output
"C:\files\Alpha" "C:\files\Beta" "C:\files\Gamma" "C:\files\Delta"
Actual output
C:\files\Alpha
C:\files\Beta
C:\files\Gamma
C:\files\Delta
The csv file is just what came to my mind first. A variable containing the files formatted like mentioned above would be sufficient. Do you have an idea?
Edit: Thank you #Matthias R. Jessen and #WaitingForGuacamole, you gave me exactly what I wanted.
(Get-ChildItem C:\scripts -File).ForEach({'"{0}"' -f $_.FullName.Replace('"','\"')}) -join " "
However, somehow my tool (written in java) is interpreting the output as one file instead of multiple files in a line.
Below the error message:
Java : Error: The file 'C:\files\Alpha C:\files\Beta C:\files\Delta C:\files\Gamma' was not found and is excluded from the transfer.
I know, that I have to handover the paths differently when using a properties file instead of entering the command manually in PowerShell.
Is there a way on letting the output look like:
"C:\\files\Alpha" "C:\\files\Beta" "C:\\files\Gamma" "C:\\files\Delta"
To pass the file paths of all children of a specific folder to a command line program as separate arguments, just pass the results of
(Get-ChildItem -File).FullName
to the program. Example:
$files = (Get-ChildItem C:\MyFolder -File).FullName
# Expected: myprogram.exe -arg1 -arg2 C:\MyFolder\file1.txt C:\MyFolder\file2.txt ...
myprogram.exe -arg1 -arg2 $files
I am doing a command line approach for making a filename content into txt file.
Here's what I've got right now.
I have got the dir command to get the names and exclude the .txt files in the folder I want to output. I was able to sort files by name using the sort-object command. And the out-file I've written down there is just to open up what I'm doing right now.
dir -n -exclude *.txt | sort-object | out-file -confirm .\<current foldername>.txt
However I want this command line to output it's unique foldername as in lets say an address is "..\folder\" & "..\folder2\" and I want to use out-file or > command in such a way that it creates folder.txt and folder2.txt, on different and multiple filetypes. Mind you I'm not talking about "filepath" for .txt filename.
Try this:
dir -n -Exclude *.txt |Sort-Object|Out-File -Confirm "$((Get-Item .).Name).txt"
Between the "" the filename is constructed. This is what happens:
The "" indicate it is a string
Within a string it is possible to embed an expression
The expression that is embedded here is (Get-Item .).Name that gets the name of the current directory (.)
To embed code in a string you have to format like this: $(<embedded code block>)
After the embedded code the string literal .txt is added
I have seen many different postings here on how to approach this task. I have tried them all with minor variations of them to no avail. Every time I run the powershell code, I still get the same error message: "cannot rename because the file does not exist..."
I just simply want to rename a bunch of files in one folder from the list of filenames I have in a text file.
Here is one version of code:
$inputFile1=#()
$filesTochange=#()
$inputFile1 = get-content H:\dev\outputfile.txt
$filesToChange = Get-ChildItem H:\dev\extractedFiles1 | Foreach -Begin
{$i=0}
-process {Rename-Item $filesToChange[$i] -newName ($inputFile1[$i] -f $i++)
}
Here is another version:
$inputFile1=#()
$filesTochange=#()
$inputFile1 = get-content H:\dev\outputfile.txt
$filesToChange = Get-ChildItem H:\dev\extractedFiles1
$i=0
foreach ($fil in $filesToChange) {Rename-Item $fil -NewName
$inputFile1[$i++]}
Not entirely sure what's your setup or desired output is but give this a whirl bud. Not the most elegant looking solutions but hopefully this is what you are looking for? Do be mindful with the sorting of the filenames in your outputfile.txt and how the folders are listed when you get the childitem.
$BasePath = 'C:\Test'
$FilesToChangeFolderName = 'extractedFiles1'
$filestochange = Get-ChildItem -Path "$BasePath\$FilesToChangeFolderName"
$FileNames = Get-Content "$BasePath\outputfile.txt"
if($filestochange.FullName.Count -eq $FileNames.Count)
{
for($i=0; $i -lt $FileNames.Count; $i++)
{
write-host "Renaming file $($filestochange.Name[$i]) to $($FileNames[$i]+".txt")"
Rename-Item -Path $filestochange.FullName[$i] -NewName ($FileNames[$i]+".txt")
}
}
Setup -
outputfile.txt contains:
renametoA
renametoB
renametoC
renametoD
renametoE
renametoF
Folder structure:
Results:
Renaming file renameto1.txt to renametoA.txt
Renaming file renameto2.txt to renametoB.txt
Renaming file renameto3.txt to renametoC.txt
Renaming file renameto4.txt to renametoD.txt
Renaming file renameto5.txt to renametoE.txt
Renaming file renameto6.txt to renametoF.txt
Explanation [TLDR]:
The script below takes a text file input which contains the name that should be used to rename each text file you have.
Example:
outputfile.txt file contains the names below:
renametoA
renametoB
renametoC
renametoD
renametoE
renametoF
There are 6 text files inside the "extractedFiles1" folder which you can see in the image.
The script actually renames the files in the "extractedFiles1" folder according to the names from the output.txt file.
Thus it follows this logic:
Renaming file renameto1.txt to renametoA.txt
Renaming file renameto2.txt to renametoB.txt
Renaming file renameto3.txt to renametoC.txt
Renaming file renameto4.txt to renametoD.txt
Renaming file renameto5.txt to renametoE.txt
Renaming file renameto6.txt to renametoF.txt
So after all the script runs your "extractedFiles1" folder's gonna look something like this:
Despite this being an older thread, I wanted to offer another "brute force" option.
CodeNagi's reply works well in PowerShell, although it took me a bit to get working.
If you already have a list with file names (output.txt) consider using excel (or OpenOffice) and the command prompt cmd.
This video is a step by step guide for some of this solution:
https://youtu.be/znhqGrF4gVQ
Open cmd with administrator privileges.
Create a list of your current (old) file names:
cd H:\dev\extractedFiles1
dir > input.txt
Open the input.txt (e.g. in Notepad). It should look like this:
Volume in drive H is Windows
Volume Serial Number is C123-4567
Directory of H:\dev\extractedFiles1
05/12/2022 11.24 .
05/12/2022 11.24 ..
05/12/2022 09.34 5,255,248 Filename1.txt
05/12/2022 09.34 5,255,952 Filename2.txt
...
Copy the lines with filenames and timestamps into an Excel sheet
Use Data > Text to columns to split the filenames from the time stamps
Copy or import your target/new filenames from output.txt next to the old filenames
Make a new column with the formula
= "ren"&" "&A1&" "&B1
resulting in something like
ren Filename1.txt FilenameA.txt
Copy all formulas and paste them in cmd. Make sure you are in the right directory.
Notes: If you have spaces in the file names, you will need to wrap each file name first in apostrophes ". Since the concatenation formula in excel doesn't accept """ (triple apostropes), make yourself a column with only " (here C) and then refer to it in the concatenation: = "ren "&C1&A1&C1&" "&C1&B1&C1&.
Further, if you have duplicate files or want to make sure they are copied correclty, you can use the MOVE function instead of rename (ren).
Instead of point 6. above do the following:
Make a new column with the formula
= "MOVE"&" "&A1&" "&"H:\dev\extractedFiles1\Renamed"&B1
Copy the created command into cmd
It will move and rename the files according to the names in B1.
This example make a copy and rename file to a list csv
Import-CSV LISTA.csv -Header newFileName | % { Copy-Item -Path archivo_convert.pdf -Destination "$($_.newfilename).pdf" }
Basically what I need is a way to scan a folder for certain files (let's say anything with .xls/xlsx) and generate a text file for each one of those files with a template layout. I figured out how to do this with the script below. However, I need it also to place the filename within the template file as well in 2 locations.
Here is how I have it now.
Get-ChildItem "*PATH*" | Foreach-Object {$_.Name} > C:\Temp\TextGenerate\FileNames.txt
Get-Content C:\Temp\TextGenerate\FileNames.txt | ForEach-Object {
Copy-Item -Path C:\Temp\TextGenerate\FileTemplate.txt -Destination ("C:\Temp\TextGenerate\ListFiles\{0}.txt" -f $_)
}
Basically it scans the folder location, creates a text file (FileNames.txt) with all the file names using a file template file (FileTemplate.txt) and creates one for each file name.
This template (FileTemplate.txt) would be like this:
REPORT-ID=TEST FILE=\\XXXXXXXXXX\XXXXXXXXXX\XXXXXXXXXXX\*insert filename here*, TYPE=XLSX, "SECTION=TEST" TOPIC-ID=TOPIC1, "TOPIC-ITEM=*insert filename here*"
Output would need to be:
REPORT-ID=TEST FILE=\\XXXXXXXXXX\XXXXXXXXXX\XXXXXXXXXXX\filename1.xlsx, TYPE=XLSX, "SECTION=TEST" TOPIC-ID=TOPIC1, "TOPIC-ITEM=filename1.xlsx"
and so on.
Everything on the template would always be the same the only thing that would need to change for each file generated would be the filename for each file found in the folder in the *insert filename here* location.
I am having a problem understand how to insert such things into the file. I would also like if possible to insert the data modified into another line of text in the generated template if possible.
As JosefZ already suggested: read the template file just once, then create the files by filling the template string with values and writing the modified string to the output files.
I would, however, recommend modifying the template to allow using the format operator (-f) on it:
REPORT-ID=TEST FILE=\\XXXXXXXXXX\XXXXXXXXXX\XXXXXXXXXXX\{0}, TYPE=XLSX, "SECTION=TEST" TOPIC-ID=TOPIC1, "TOPIC-ITEM={0}"
Also, there's no need to write the names to a file first. Change your code to something like this:
$template = Get-Content 'C:\Temp\TextGenerate\FileTemplate.txt' | Out-String
Get-ChildItem "*PATH*" | Select-Object -Expand Name | ForEach-Object {
$path = "C:\Temp\TextGenerate\ListFiles\{0}.txt" -f $_
$content = $template -f $_
Set-Content -Path $path -Value $content
}