Powershell issue with writing editing files that contain ' in filename - powershell

I wrote a script that supposed to change a certain word in a text file to the name of another file that has been dragged and dropped on onto it.
The drag and drop and recognition of the filename work without any issue.
When trying to write the file with PowerShell there is always an error message popping up.
powershell -Command "(Get-Content "%TemplatePath%").replace("[NAME]","!item_%%n!") | Out-File -encoding ASCII "!item_%%n!".txt"
the error messagethat pops up is
At line:1 char:79
... Templates\master.txt).replace([NAME],D:\Temp ...
Missing expression after ','.
At line:1 char:79
... Templates\master.txt).replace([NAME],D:\Temp ...
Unexpected token 'D:\Temp' in expression or statement..
+ CategoryInfo : ParserError: (:) [], ParentContainsErrorRecordException
+ FullyQualifiedErrorId : MissingExpressionAfterToken

Ok. I found the solution to the issue.
powershell -Command "(Get-Content \"%TemplatePath%\").replace(\"[NAME]\",\"!item_%%n!\") | Out-File -encoding ASCII \"!item_%%n!\".txt"
However, the problem is now that the if I use ASCII the single-quote in Don't is converted into an ? and looks like Don?t.
Using UTF8 works but the problem is its UTF8 with BOM.
And the program that I use to open the files does not work with BOM.
Is there any way to change the UTF8 BOM to UTF8 or to fix the ' to ? cenovertion?

Related

Change graph output encoding in pipe (powershell)

I'm using terraform on windows, and would like to visualize the graphs using Graphviz. However, there is a difference between the encoding that is being output by Terraform vs what Graphviz expects. Ideally, I want to do the following:
terraform graph -draw-cycles | dot -Tsvg > output.svg
That doesn't work, because the output that is being given by terraform is in the wrong encoding. The following sequence works, but uses an intermediate file:
terraform graph -draw-cycles > output.tmp
Get-Content .\output.tmp | Set-Content -Encoding Ascii output2.tmp
dot -Tsvg output2.tmp > output.svg
rm output.tmp
rm output2.tmp
However, I would like to do this without intermediate files using piping. A statement such as
terraform graph -draw-cycles | Set-Content -Encoding Ascii -PassThru | dot -Tsvg > output.svg
doesn't work. The output from the terraform graph statement is text, and apparantly the Set-Content commandlet needs additional information (Path?):
Set-Content : The input object cannot be bound because it did not contain the information required to bind all mandatory parameters: Path
At line:1 char:32
+ ... rm graph -draw-cycles | Set-Content -Encoding Ascii -PassThru | dot - ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (digraph {:PSObject) [Set-Content], ParameterBindingException
+ FullyQualifiedErrorId : InputObjectMissingMandatory,Microsoft.PowerShell.Commands.SetContentCommand
Any suggestions?
After reading the article referred to by zett42, I saw a reference to CMD pipe different form Powershell pipe? in the comments.
The easiest solution for my specific case is simply executing the call with cmd:
cmd /c "terraform graph -draw-cycles | dot -Tsvg > output.svg"
Using the Invoke-WithEncoding would also work, but is a little more involved.

Select a string from a tailing log

I have an application log for which I am trying to write a batch file that will tail the log and return strings that contain "queue size" so that the updating queue size can be displayed. Basically the Windows equivalent of:
tail -f app.log | grep "queue size"
From what I've read I would need to use Windows powershell. I have devised the following script:
powershell -command Select-String -Path C:\logs\app.log -Pattern "queue size"
This gives me the following error:
Select-String : A positional parameter cannot be found that accepts
argument 'size'. At line:1 char:1
+ Select-String -Path C:\logs\app.log -Pattern queue size
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (:) [Select-String], ParameterBindingException
+ FullyQualifiedErrorId : PositionalParameterNotFound,Microsoft.PowerShell.Commands.SelectStringCommand
Although this as it stands doesn't work, would it constantly update with the current logic?
No, the PowerShell command will not continue to read the log as it's being updated. PowerShell can't really handle this task, so you'd be better off grabbing a Windows port of the Unix tail command (e.g. from GnuWin32 or UnxUtils) and use it with the batch find command:
tail -f C:\path\to\app.log | find "queue size"
You need to wrap the command in double quotes and use single quotes for the pattern:
powershell -command "Select-String -Path C:\logs\app.log -Pattern 'queue size'"
this should do:
cat c:\path\to\app.log -tail 100 -wait | select-string "queue size"
cat is an alias for Get-Content...
The -wait parameter will make it wait for log updates.

Powershell variables in command not working

I've tried a ton of different variations of this, but I can't get it to work. I am trying to run mysqldump to export a database (in this case called global).
PS C:\Users\Administrator> &"$mysqlpath\mysqldump.exe -u$mysqluser -p$mysqlpass --databases global | Out-File $env:TEMP\database_backup\global_$timestamp.sql -Encoding UTF8"
& : The term 'C:\Program Files\MySQL\MySQL Server 5.6\bin\mysqldump.exe -ubackup -pbackup_password --databases global | Out-File C:\Users\ADMINI~1\AppData\Local\Temp\2\database_backup\global_2013-12-11T11:47:28.sql -Encoding UTF8' is
not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or
if a path was included, verify that the path is correct and try again.
At line:1 char:2
+ &"$mysqlpath\mysqldump.exe -u$mysqluser -p$mysqlpass --databases global | Out-Fi ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (C:\Program File... -Encoding UTF8:String) [], CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException
It looks like it is being exploded into the proper variable names, but I can't get it to run.
UPDATE: So that was the right answer, I had a : in the timestamp. My other problem was solved by putting the variables inside double quotes (")
You are telling Powershell to run an EXE named
&"$mysqlpath\mysqldump.exe -u$mysqluser -p$mysqlpass --databases global | Out-File $env:TEMP\database_backup\global_$timestamp.sql -Encoding UTF8"
So remove the quotes (") and try again. Like so,
& $mysqlpath\mysqldump.exe -u$mysqluser -p$mysqlpass --databases global | Out-File $env:TEMP\database_backup\global_$timestamp.sql -Encoding UTF8

Renaming file with square brackets is not working as expected in Powershell

I've been working on this one issue for abut a week, and think I'm missing something obvious...I need a couple sets of eyes.
Starting with this question I researched all the links provided in the answer, and I'm running the following script, gleaned from MS Connect:
$txtPath = "c:\users\xxxxxx\desktop\cgc\tx"
$txtPath2 = "c:\users\xxxxxx\desktop\cgc\tx2"
get-childitem $txtPath | foreach {
Move-Item -literalpath $txtPath2.Name $_.Name.Replace ("]" | "[", "_")
}
Both paths exist. *\tx contains 35 *.txt files, some with square brackets in the name, some without. *\tx2 is currently empty, awaiting output files from the script.
If I've written my third statement properly, I'm passing each child from \tx to the function where square brackets are changed to an underscore as the file is moved and re-saved to the new location, \tx2.
Unfortunately, I get this error:
Expressions are only allowed as the first element of a pipeline.
At C:\users\xxxxxx\desktop\cgc\rni.ps1:4 char:71
+ Move-Item -literalpath $txtPath2.Name $_.Name.Replace ("]" | "[", "_" <<<< )
+ CategoryInfo : ParserError: (:) [], ParseException
+ FullyQualifiedErrorId : ExpressionsMustBeFirstInPipeline
If I'm interpreting the error correctly, something's preventing the close paren to be recognized. Do I need some kind of escape character for the brackets? I tried using a backtick escape and backslash escape inside the quotes, but that led to the same error.
With the escape outside the quotes, I got this error.
The term '\]' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling
of the name, or if a path was included, verify that the path is correct and try again.
At C:\users\xxxxxx\desktop\cgc\rni.ps1:4 char:61
+ Move-Item -literalpath $txtPath2.Name $_.Name.Replace (\"]" <<<< | \"[", "_")
+ CategoryInfo : ObjectNotFound: (\]:String) [], CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException
What am I missing?
You got the syntax wrong:
$_.Name.Replace ("]" | "[", "_")
is just nonsense. Usually it would mean “Call the Replace method on $_.Name with the return value of the following as argument: Pipe the string ']' as input into the command '[', '_'”. But here lies the first problem: That's no command, it's an expression and that cannot work. Then the problem is that this is the argument to a cmdlet. Special rules apply here and they usually say “convert to string everything that isn't in parentheses”. So there isn't even a method call, you'd get the method declaration as the new file name and pass another argument that suffers from the problems described above.
If I'd have to guess I'd think you want to replace square brackets by underscores. If so, then use the following:
Move-Item -literalpath $txtPath2.Name ($_.Name -replace '\[|]', '_')

Trying to copy a group of files contained in a text file

I'm trying to copy a list of files from a txt file and as a newbie, I'm having a hard time.
Here is a bit of the text file. The real file has no extra lines, but I had to do that to :
"D:\Shared\Customer Care\Customer Care Common\Customers Contracted\Customers Contracted\Fred 44705"
"D:\Shared\Customer Care\Customer Care Common\Customers Contracted\Customers Contracted\Johnson 47227"
"D:\Shared\Customer Care\Customer Care Common\Customers Contracted\Customers Contracted\Daniel 35434"
"D:\Shared\Customer Care\Customer Care Common\Customers Contracted\Customers Contracted\Frank, John 48273"
I've tried enclosing the filename string in double-quotes as well.
Here's the simple script I'm trying to use:
Get-Content c:\users\scripts\files-to-fix.txt | Foreach-Object {copy-item $_ d:\junk}
The error I'm getting is:
Copy-Item : Cannot find drive. A drive with the name ''D' does not
exist. At C:\users\mhyman\scripts\copyfiles.ps1:2 char:81
+ Get-Content c:\users\mhyman\scripts\files-to-fix.txt |
Foreach-Object {copy-item <<<< $_ d:\junk}
+ CategoryInfo : ObjectNotFound: ('D:String) [Copy-Item],
DriveNotFoundException
+ FullyQualifiedErrorId :
DriveNotFound,Microsoft.PowerShell.Commands.CopyItemCommand
I know this is simple, but I would really appreciate some help.
I think it is the surrounding quotes that are causing the problem ( as indicated by the error saying that a drive of name "D is not found. Try this:
get-content c:\users\scripts\files-to-fix.txt | %{ copy-item $_.trim('"') d:\junk}
Of course, if you can control the txt file, enter the list without the quotes.
By your tags and drive letters and backslashes it is clearly a Windows environment your working in and although I'm not a PowerShell scripter, I'm a better than most batch scipter and use a For / If conditioanla statement sicne it is shorter and you feed it your file instead of parsing out the file into reduudc commands on a line, so in your example:
for /F %%t in (the text file.txt) do copy /q %%t d:\junk
And then you go home and never worry about until the next morning
Does powershell have a runas ornative mode that can parse older, more proven and stable DOS commands ?