using "CON" as filename - powershell

I was copying a huge number of png and txt files using Copy-Item cmdlet, and sadly I discovered that a funny programmer decided to use "CON" as file name to recap connection information.
Given that "con" is a reserved word and Copy-Item returns:
Copy-Item : Cannot process path 'xxx\con.txt' because the target represents a reserved device name.
and given that this name can't be changed and it's used in every folder I need to copy,
Is there a way to copy all these "con.cfg" and "con.txt" files using Powershell?
I googled but I found only advice like "Don't use con!" or "Don't use Powershell to copy these files".

I haven't been able to find a solution for PowerShell yet, but you should be able to rename the files via command prompt using something like this:
ren \\.\<absolute path> <new name>
So for example:
ren \\.\C:\stuff\con.cfg stuff.cfg
You could invoke the command prompt through PowerShell, of course:
cmd /c "ren \\.\C:\stuff\con.cfg stuff.cfg"
And obviously you could use PowerShell variables in there if you wanted
$dir = "C:\stuff"
cmd /c "ren \\.\$dir\con.cfg stuff.cfg"

You could try referring to them using a wildcard: *on ?
Example:
ls | ? {$_.Name -match "*on.cfg"} | del
Regex example:
ls | ? {$_.Name -match "^\won\.cfg"} | del

Related

Is there a way to "get-clipboard" and use the referenced clipboard info in a command line?

I'm making a script to convert a PDF to txt file.
I'm trying to copy a file name and then use the copied file name in the next line of the script. But using get-clipboard doesn't include that data in the same command line. Is there a way to essentially ctrl+v it in that line using PS?
PS C:\Users\PiRho> #(get-childitem C:\Users\PiRho\Desktop\PDF_Convert -name) [0] | set-clipboard
PS C:\Users\PiRho> cd C:\Users\PiRho\Desktop\PDF_Convert
PS C:\Users\PiRho\Desktop\PDF_Convert> .\pdftotext -table | get-clipboard
I/O Error: Couldn't open file 'get-clipboard'
So this is the old way I was doing it.
PS C:\Users\PiRho> #(get-childitem C:\Users\PiRho\Desktop\PDF_Convert -name)[0] | set-clipboard
PS C:\Users\PiRho> cd C:\Users\PiRho\Desktop\PDF_Convert
PS C:\Users\PiRho\Desktop\PDF_Convert> .\pdftotext -table #Ctrl+V#
The #Ctrl+V# is done using my macro, but it will sometimes use the previous clipboard info.
Effectively I'm looking for a replacement Ctrl+V in powershell that doesn't rely on a macro to put the file name there.
Easiest way is to use Variables so something like:
$File = #(get-childitem C:\Users\PiRho\Desktop\PDF_Convert -name)[0]
cd C:\Users\PiRho\Desktop\PDF_Convert
.\pdftotext -table $File.FullName

Apply setCaseSensitiveInfo recursively to all folders and subfolders

I am trying to configure my dotnet core project (in Windows) as "case sensitive", so it behaves as in my production server (linux).
I have found this way of doing it:
fsutil.exe file setCaseSensitiveInfo "C:\my folder" enable
The problem is that this function is not recursive:
The case sensitivity flag only affects the specific folder to which you apply it. It isn’t automatically inherited by that folder’s subfolders.
So I am trying to build a powershell script that applies this to all folders and subfolders, recursively.
I have tried googling something similar and just modifying the command line, but I don't seem to find the corrent keywords. This is the closest that I've gotten to this sort of example.
Correct code:
(Get-ChildItem -Recurse -Directory).FullName | ForEach-Object {fsutil.exe file setCaseSensitiveInfo $_ enable}
Explanation:
NOTE: The code in the answer assumes you're in the root of the directory tree and you want to run fsutil.exe against all the folders inside, as it's been pointed out in the comments (thanks #Abhishek Anand!)
Get-ChildItem -Recurse -Directory will give you list of all folders (recursively).
As you want to pass their full path, you can access it by using .FullName[1] (or more self-explanatory | Select-Object -ExpandProperty FullName ).
Then you use ForEach-Object to run fsutil.exe multiple times. Current file's FullName can be accessed using $_ (this represents current object in ForEach-Object)[2].
Hint:
If you want more tracking of what's currently being processed you can add the following to write the path of currently processed file to the console: ; Write-Host $_ (semicolon ; is to separate from fsutil invocation) as it was pointed out in the comments (thanks Fund Monica's Lawsuit !)
[1] .FullName notation works for PowerShell 3.0 and greater, Select-Object -ExpandProperty FullName is preferred if there's a chance that lower version will be used.
[2] $_ is an alias for $PSItem
(Get-ChildItem -Recurse -Directory).FullName | ForEach-Object {if (-Not ($_ -like '*node_modules*')) { fsutil.exe file setCaseSensitiveInfo $_ enable } }
I modified #robdy's code to allow excluding node_modules. You can replace the "node_modules" bit in the above with anything to exclude filepaths containing it.
If you're working with npm, you probably want to exclude node_modules. #robdy's answer is great, but was taking minutes at a time iterating over every single node package folder even if I didn't have the package installed; given that this is something one might want to run fairly often since directories might be added all the time, and since you probably aren't modifying anything in node_modules, excluding it seems reasonable.
With Cygwin and bash shell, you can do this:
$ find $THEDIR -type d -exec fsutil file setCaseSensitiveInfo "{}" enable \;
It appears that Windows handles the '/' characters output by the find command just fine.
In my case I had to first enable the Linux subsystem before using the fsutil tool. So my steps were:
Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Windows-Subsystem-Linux
then restart, and then #robdy 's solution:
(Get-ChildItem -Recurse -Directory).FullName | ForEach-Object {fsutil.exe file setCaseSensitiveInfo $_ enable}
On windows 11, the other answers are not correct, as fsutil requires that the directory is not empty. To overcome this, I created a NEW empty directory, used fsutil file setCaseSensitiveInfo to set the case sensitive flag on the new directory, then MOVED the files from the other directory inside the new one. This works, as the directories are re-created when moved, and new directories inherit the case sensitive flag.

Change directory in PowerShell

My PowerShell prompt's currently pointed to my C drive (PS C:\>). How do I change directory to a folder on my Q (PS Q:\>) drive?
The folder name on my Q drive is "My Test Folder".
Unlike the CMD.EXE CHDIR or CD command, the PowerShell Set-Location cmdlet will change drive and directory, both. Get-Help Set-Location -Full will get you more detailed information on Set-Location, but the basic usage would be
PS C:\> Set-Location -Path Q:\MyDir
PS Q:\MyDir>
By default in PowerShell, CD and CHDIR are alias for Set-Location.
(Asad reminded me in the comments that if the path contains spaces, it must be enclosed in quotes.)
To go directly to that folder, you can use the Set-Location cmdlet or cd alias:
Set-Location "Q:\My Test Folder"
Multiple posted answer here, but probably this can help who is newly using PowerShell
SO if any space is there in your directory path do not forgot to add double inverted commas "".
You can simply type Q: and that should solve your problem.
Set-Location -Path 'Q:\MyDir'
In PowerShell cd = Set-Location
You can also use the sl command to be able to change directories. It is Set-Location but it is much shorter.
Example:
# Too verbose
Set-Location -Path C:\
# Just the right amount of characters to type
sl C:\
If your Folder inside a Drive contains spaces In Power Shell you can Simply Type the command then drive name and folder name within Single Quotes(''):
Set-Location -Path 'E:\FOLDER NAME'
The Screenshot is attached here
On Powershell use Set-Location instead of cd.
Put path in quotes. Single quotes works for me.
Set-Location 'C:\Program Files\MongoDB\Server\6.0'

How to to copy all the files available in my TFS source server to a folder in a directory?

I want to copy all the files available in my TFS source server to a folder in a directory. I tried the below code but error is coming while achieving the same. Can you suggest a solution?
PS> C:\Windows\System32> Get-TfsItemProperty $/MyFirstTFSProj -r `
-server xyzc011b| Where {$_.CheckinDate -gt (Get-Date).AddDays(-150)} |
Copy-Item D:\john\application1 -Destination C:\Test -whatif
Copy-Item : The input object cannot be bound to any parameters for the command
either because the command does not take pipeline input or the input and its pr
operties do not match any of the parameters that take pipeline input.
At line:2 char:14
+ Copy-Item <<<< D:\Deepu\SilverlightApplication5 -Destination C:\Test -w
hatif
I would just create a workspace/workfolder mapping and use the tf.exe tool to get the files at the date you interested in e.g.:
PS\> cd <root_of_workfolder_on_local_harddrive>
PS\> tf get . /r "/v:D$((Get-Date).AddDays(-150))"
If this isn't the final destination then just copy the dir contents to the destination. If you don't need the workspace any longer, then delete it.
BTW I use the PowerTool cmdlet quite a bit but find it primarily useful for queries. For instance, AFAICT, there is no equivalent of "tf get" which you need to pull down the files from the server. IOW, you can't use copy-item to copy the files from the TF server. You have to use a tf command to retrieve the file from the server.
ANSWER ACHIEVED FOR MY QUESTION
I am posting final answer.With the help of this script we can copy all the file from a TFS server and copy all the checked in files from a particular date to the local hard drive while maintaining the hierarchy at the same time.
Enjoy..!!
Get-TfsChildItem $/MyFirstSpectaProj -r -server xyz10co553 |
? { $_.CheckinDate -gt (Get-Date).AddDays(-01) } |
% { $_.DownloadFile(#(join-path C:\test\xyz $_.ServerItem)) }

Test-Path behavior in Powershell

I'm trying to write a script in powershell to batch convert video files.
The way I intend to use it is to go to some folder full of video files and run it. It uses a conversion program that can be run in "command-line mode" (named handbrake) and saves the converted files with "-android" appended to them before the file extension. For example, if I have a file named video1.avi in the folder, after running the script the folder has 2 files: video1.avi and video1-android.avi
The reason I want to do this this way is so that I can check if, for each video file, there is a converted version of it (with -android appended to the name). And if so, skip the conversion for that file.
And this is where I'm having touble. The problem is the Test-Path's behavior (the cmdlet I'm using to test if a file exists).
What happens is, if the video file has an "unusual" name (for example in my case it's video[long].avi) Test-Path always returns False if you try to check if that file exists.
An easy way for you to test this is for example to do this:
Go to an empty folder,
run notepad to create a file with "[" in its name:
&notepad test[x].txt
Save the file
then do this:
Get-ChildItem | ForEach-Object {Test-Path $_.FullName}
It does not return true! It should right? Well it doesn't if the file has "[" in its name (I didn't check for any other special characters)
I've realized that if you escape the "[" and "]" it works
Test-Path 'test`[x`].txt'
returns true.
How can I go around this issue? I want to be able to: given a BaseName of a file, append it "-android.avi" and check if a file with that name exists.
Thanks,
Rui
Many PowerShell cmdlets have Path parameters that support wildcarding. As you have observed, in PowerShell not only is * a wildcard but [ and ] are also considered wildcard characters. You can read more about this in the help topic about_Wildcards.
For your issue, if you don't need wildcarding then I would recommend using the -LiteralPath parameter. This parameter doesn't support wildcarding and accepts [ and ] as literal path characters e.g.:
Get-ChildItem | ForEach {Test-Path -LiteralPath `
"$([io.path]::ChangeExtension($_.FullName,'avi'))"}
FYI, the reason piping the output of Get-ChildItem directly into Test-Path works is because the LiteralPath parameter has an alias "PSPath" that maps to the PSPath property on the FileInfo object output by Get-ChildItem. That property gets bound to the LiteralPath (er PSPath) parameter "by property name".
dir | % {test-path "$($_.Name)-android.avi"}