Changing file extension case in Powershell - windows

We have .txt files sent by users which are encrypted. We decrypt them and send it to a 3rd party system downstream as input. It had been working well but users started to send files are .TXT instead of .txt. It doesn't make any difference during decryption but it is affecting the downstream system. We are supposed to change the .TXT to .txt
I tried changing it this way
Copy-Item -Path $myOfile –Destination ([io.path]::ChangeExtension($myOfile, '.txt')) -Verbose
Here $myOfile is my file name and it named something like this
20160506_205400_Sender_header.TXT.GPG which we decrypt and it changes to 20160506_205400_Sender_header.TXT
I used the above command to change it to 20160506_205400_Sender_header.txt and it throws the below error
Copy-Item : Cannot overwrite the item C:\Sender\Submit\20160506_205400_Sender_header.TXT with itself.
It appears as if there is no distinction between .TXT and .txt. Is there a way to do it or a workaround?

Windows is not case-sensitive when it comes filepaths, so a copy-operation with the same destination and source will fail because you're reading the file your trying to replace.
Use Rename-Item to rename files. Ex:
Rename-Item -Path $myOfile -NewName ([io.path]::ChangeExtension($myOfile, '.txt')) -Verbose

Related

Powershell reroute output files of exe into directory

We have an internal process set up in Powershell which runs an exe file internal.exe which creates a lot log files in an absolute path "C:\This\is\absolute" which contains all the log files of the past 30 days. "C:\This\is\absolute" contains also log files from other applications and while internal.exe runs and creates log files in "C:\This\is\absolute" another application might create a log file there as well.
Now we need to send the log files created by internal.exe and for this they have to be moved to another folder "C:\Move\here" after having been created.
The process is currently simply set up as
Start-Process -FilePath "internal.exe"
I was looking for something like
Get-Outputfiles (Start-Process -FilePath "internal.exe") | foreach {Move-Item -Path $_ -Destination "C:\Move\here"}
but I found only ways to write output to files, e.g., via Out-File. Is there a way to get something like the Get-Outputfiles which lists the paths of output files from a process?

Update context menu of all file extensions in Windows via powershell takes long time

Developing our own application for our company only, we have developed script used for installation from shared drive. Except the installation itself, the script should also create/update values in the registry of particular user (HKEY_CURRENT_USER).
These values are separated for:
Directories (HKCU:\Software\Classes\Directory)
All File Extensions (HKCU:\Software\Classes\*)
For the directory folder the update is immediate, where for the extensions it seems to take quite some time depending on machine hardware (from 40 sec to 2 minutes).
Now there is a trouble to create "entry" in the registry for the folder named * only. I've got a question for this to resolve (PowerShell: How do I create selector on file/folder, whose name is '*' (asterisk/star)?).
Ignoring the issue above, we have found some solution how the string path works, however I'm not sure what is happening behind the code and do not understand why it takes so long time.
# Directory
New-Item -Path "HKCU:\Software\classes\Directory" -Name "shell" | Out-Null
# All Files Extension
New-Item -Path "HKCU:\Software\classes\[*]" -Name "shell" | Out-Null
One idea is that the [*] solution actually goes through all the file extensions, but the registry itself is showing this NewItem under * folder and not shown under particular extensions:
Another idea about this, is when we have a registry file (*.reg), by running the file the registry entry is added immediately and resolve the case.
Questions:
What is actually happening when we are running the query to add entry under [*] selector?
How can be this process optimized to lower the time for creating new folder in registry for all files' extension?
I suspect what's happening is that the -Path in your New-Item call is recursive because of the wildcard. Hence the delay.
Here's a workaround to the issue:
Set-Location -LiteralPath "HKCU:\Software\classes\*"
New-Item -Name "shell"
New-Item uses the current location as the -Path if not explicitly passed to the function.

How to use short-cut paths to Compress-Archive to zip current folder into same destination

I am using Compress-Archive and want to zip the current directory into the same path. However I do not want to have to type out the entire file path both times. Is there an easy way to do this?
I am using windows 10 pro.
This works for the most part Compress-Archive . test.zip but I want it to be on the same level as the current directory so I need to put it back one spot.
Something like this is what I want:
path/test
path/test.zip
What I am getting:
path/test
path/test/test.zip
It is going inside the actual folder which is not what I want
You propably want that:
Compress-Archive * ..\test.zip
The wildcard * avoids that the name of the folder is put inside the zip.
Using .. for the output path we go one level up in the directory tree.
This command will fail if test.zip already exists. Either add parameter -update to update the archive or add -force to overwrite the archive. Both can be used even if the archive does not already exist.
If the current working directory is "t", it can be included using the following command. I would note that I do not think putting the destination .zip file in the directory being compressed is a good idea.
Compress-Archive -Path $(Get-ChildItem -Recurse -Exclude t.zip) -DestinationPath .\t.zip -Force
It is shorter if you are willing to use aliases and cryptic switches.
Compress-Archive $(gci -r -e t.zip) .\t.zip -Force
If I have misinterpreted your situation, please leave a comment or improve the information provided by editing the question.

Evaluating Variables first in PowerShell Commands

I'm trying to get PowerShell to evaluate variables before executing a command, for example:
$OutputPath = "C:\Temp"
Get-ChildItem -include *.mp3 | Move-Item -Destination $OutputPath
However, the Move-Item cmdlet tries to interpret this literally, so it doesn't get moved. The script works fine whenever I enter the path directly, but I need to be able to control the path with a variable. How do I do this?
This answer could evolve but as your question stands I see a big issue that is unfortunately poorly documented. -Include and -Exclude only perform their intended functions when partnered with -Recurse. Used without it can yeild 0 results. In your case that would mean nothing is passed through the pipe and Move-Item is not executed.
Currently you are just filtering on *.mp3 which is basic and can just be used with the -filter parameter. While you don't need to I would recommended specifying -Path as well so that you move the files you wanted.
Get-ChildItem -Filter *.mp3 | Other-Stuff ...
You mentioned in comments the following error:
Move-Item : Cannot create a file when that file already exists.
That error is very specific. Either from previous testing or an oversight in new names that file indeed already exists. Two things you can do to help with that problem is use the -WhatIf switch which should quote a file path on the verbose stream so you know where the file would end up.
Second, if you understand the data risk, is to use -Force so that the file will be overwritten by the new one. With Copy-Item it is not a big deal since the original file still exists. Mistakes with Move-Item can be permanent.

Renaming a file and remove 'dot' and replace it with' _'

I have set of files in a folder with name like abcd.15678
I want to remove the . and replace it with _
Pls suggest the windows command to do this
This solution is reposted from How to Batch Rename Files in Windows: 4 Ways to Rename Multiple Files by Chris Hoffman
PowerShell offers much more flexibility for renaming files in a command-line environment. Using PowerShell, you can pipe the output of one command – known as a “commandlet” in PowerShell terms — to another command, just like you can on Linux and other UNIX-like systems.
First of all, open Powershell ISE and then navigate to the directory (folder) that has the files and folders you'd like to rename by using this command:
cd "C:\your\directory\"
The two important commands you’ll need are Dir, which lists the files in the current directory, and Rename-Item, which renames an item (a file, in this case). Pipe the output of Dir to Rename-Item and you’re in business.
After you launch PowerShell ISE, use the cd command to enter the directory containing your files. You should put the files in their own directory so you don’t accidentally rename other files.
For example, let’s say we don’t want the dot character in our file names – we’d rather have an underscore instead.
The following command lists the files in the current directory and pipes the list to Rename-Item. Rename-Item replaces each dot character with an underscore.
Dir | Rename-Item –NewName { $_.name –replace ".","_" }
Consult Microsoft’s documentation on the Rename-Item commandlet if you want help performing other, more advanced operations.
There isn't a windows command to do this. You should consider writing a script of some sort that obtains a directory listing and enumerates through each entry: changes the dot to an underscore, and calls the windows rename command appropriately.
Actually this should work :
Dir | Rename-Item –NewName { $_.Name.Replace(".","_") }

Resources