What is the ">" operator in PowerShell? - powershell

I've tried searching around for this, and I can't find an answer, partially because it's difficult to search for the ">" character and also because the prompt in PowerShell uses that character.
I've got an example that works well, but I don't know what this line is doing exactly:
New-Item $tempCmd -Force -Type file > $null
I get the New-Item call and its parameters, but what is "> $null" doing exactly? And specifically what role does ">" play in this statement?

The > character does output redirection.
In an example it seems like it suppresses the output by redirecting it to null.

Microsoft has published a language specification for PowerShell 2.0 and PowerShell 3.0.
From version 3.0:
The redirection operator > takes the standard output from the pipeline and redirects it to the location designated by redirected-file-name, overwriting that location's current contents.
Your example has a null filename, so the output goes nowhere.
As nochkin says, people normally do this to stop a command from producing output. By default New-Item will output metadata about the new item to the host.
To acheive the same thing in a more readable way you can pipe the output to Out-Null.
New-Item $tempCmd -Force -Type file | Out-Null
From the documentation:
Deletes output instead of sending it down the pipeline.

Related

How do i use Get-clipboard output in a powershell script?

i'm trying to use text that is inside the clipboard inside a powershell script. So what the purpose for the script, i want to be able to copy a file directory and then run the script so it uses the copied directory as a automatic destination. So my idea was to do something like this:
Copy-Item C:\Users\gif.gif -Destination "Copied Directory"
I'm very new to powershell scripting, so an explenation of what is going on would be nice but not needed. I origionlly thought that this could work but nope XD, this should have been a simple project but yeah it wasn't meant to be easy.
Copy-Item C:\Users\J.J\Documents\TouchPortal/Make_30fps_gif.bat -Destination | Get-Clipboard
Would love to get some help with this, and thank you in advance!
To complement Steven's helpful answer:
In Windows PowerShell only, you can use Get-Clipboard's -Format parameter to request clipboard data other than text.
In PowerShell [Core, v6+], this is no longer supported, and text is indeed the only data type supported by Get-Clipboard.
In Windows PowerShell, if you've used File Explorer to copy a directory to the clipboard (using the regular Copy shortcut-menu command or the Ctrl+C keyboard shortcut), you can access it as System.IO.DirectoryInfo instance by passing -Format FileDropList to Get-Clipboard.
Note: -Format FileDropList returns a collection of file-system-info objects, so as to also support multiple files/directories having been copied to the clipboard; thanks to member-access enumeration, however, you can treat this collection like a single object - assuming truly only one file or directory was copied.
# Note: Windows PowerShell only.
# The .FullName property returns the full directory path.
Copy-Item C:\Users\gif.gif -Destination (Get-Clipboard -Format FileDropList).FullName
In PowerShell [Core, v6+] you'll indeed have to use the Shift+right-click method and select Copy as path from the shortcut menu, in order to ensure that a file/directory is copied as a (double-quoted, full) path string, as shown in Steven's answer.
In PowerShell core including versions 6 & 7 Get-Clipboard only works with text. If you use it after copying a folder it will return null.
In PowerShell 5.1 (Windows PowerShell) you can use the -Format parameter with Get-Clipboard
See mklement0's answer for a better description and example using -Format.
If you need to use the newer versions, you can use the shift + context menu choice > Copy as Path to get the folder's string path on to the clipboard, but that will quote the path. The quoted path will then be rejected by Copy-Item.
However, you could quickly replace the quotes like below.
Copy-Item 'C:\temp\BaseFile.txt' -Destination (Get-Clipboard).Replace('"',"")
Caution though, this seems hazardous and I wouldn't advise it. I use Get-Clipboard all the time to get data into a console session and can attest that it's too easy to make mistakes. The clipboard is so transient and it's use so ubiquitous that even if you make this work it's bound to burn you at some point.
Maybe you can elaborate on what you're trying to do and why. Then we can brainstorm the best approach.

Alternatives to invoke-expression

I have this function:
function traced()
{
write-host "$args"
invoke-expression -Command "$args"
}
and I use it in several places like traced cp "$($_.FullName)" (join-path $directory $newfile) so that I have a log of all of the places that get copied (or removed, or whatever)
But when the directory contains spaces and dashes, it results in invoke-expression throwing.
I guess I could just define traced-cp and traced-rm, but if I have a lot of functions I want to trace, what's the generic answer? I just want a function that prints, then evaluates, the exact command its given. From what I understand, the & operator isn't what I want here-- It won't work for shell builtins.
[...] so that I have a log of all of the places that get copied (or removed, or whatever)
I'd strongly recommend you use transcript logging for this!
You can start a transcript interactively with the Start-Transcript cmdlet, but if you want to keep a transcript of every single instance of PowerShell you launch by default, I'd suggest turning it on by default!
Open the local policy editor (gpedit.msc) on your Windows box and navigate to:
Computer Configuration
> Administrative Templates
> Windows Components
> Windows PowerShell
Select the policy setting named "Turn on PowerShell Transcription", set it to Enabled, and optionally configure your preferred output directory (defaults to your home folder).
This way, you'll always have a full transcript of your interactions in PowerShell :)
Consider using argument splatting to build your command instead of building a string-based command with Invoke-Expression. I also don't know where you heard that & doesn't work with shell built-ins but it works with both commands and cmdlets.
Here is the official Microsoft documentation on splatting in Powershell.
This approach also eliminates the difficulty in crafting a command string correctly, having to escape characters, and dealing with path spaces - using splatting with named or positional arguments takes care of most of this for you.
I would suggest using -verbose with copy-item or remove-item, and also -passthru with copy-item.

Error in batch file due to space

I am having trouble with a seemingly simple script I have which essentially copies an item from the user's PC and places it on another computer; however, the destination file path contains a space in it. I have tried multiple methods of correcting this issue (some I don't completely understand) from using double quotation marks around the string to forcing it to run powershell.
To give a very brief precursor to this situation, I must add that I initially created this script using Powershell on Windows 10 and I should also add that it works completely fine in Powershell, just not as a .bat. I understand there may be some differences in the languages or what is interpreted through the programs.
Here is the string in the question:
Copy-Item $ENV:USERPROFILE\Desktop\VAST.accdb -destination "\\PRECDP19670\C$\Users\WAKE\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup" -Force -PassThru -Verbose
The destination contains the space in the filepath.
Any help is appreciated!
As Bill mentioned, your BAT file needs to call PowerShell as an executable.
PowerShell.exe -command 'Copy-Item $ENV:USERPROFILE\Desktop\VAST.accdb -destination "\\PRECDP19670\C$\Users\WAKE\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup" -Force -PassThru -Verbose

how to use wmi with powershell to target a specific printer for output

I have an amazing script i am going to use to for a bespoke print solution. There is one thing left to do. The script utilizes Start-Process –FilePath “c:\testfolder\*.docx” –Verb Print
how can i make it so it targets an installed printer on the client system without targeting/using the default printer? (another VBScript already uses the default).
PSVersion5. + W764bit
(New-Object -ComObject WScript.Network).SetDefaultPrinter('Xerox Floor X')
This does the trick, it will select the relevant default printer and then i can run another line which will default it back to the original default printer after the script runs.
Some issues with parentheses running and defaulting it back before it prints at the moment though.
I dont think you can specify the printer when using the Print verb. What you can do is this:
Get-ChildItem -Path "C:\testfolder" -Filter *.docx | Out-Printer "\\Server01\Prt-6B Color"
Get all items in path with extension .docx pass to Out-Printer
More on Out-Printer

How to call findstr with /G parameter in powershell

I use findstr to recursively search several large directories for any lines that match any of the lines in searchList.txt.
findstr /SNIP /D:"C:\search Dir1;C:\search Dir2" /G:C:\searchList.txt *
I want to do the same thing in a Powershell script, either by calling the findstr command or doing something entirely in Powershell. Iterating over each item in searchList.txt and then looking in all the directories is too slow.
How do I call the above line in Powershell, or do the equivalent?
Thanks in advance.
You can call it in PowerShell by opening a PowerShell prompt, typing it in, and hitting [ENTER].
I don't see anything preventing you from running that command from PowerShell. findstr is not a native cmd command, it's a standalone .exe file bundled with Windows and located in the default system path (the System32 directory), so it's available from PowerShell.
You could do it in native PowerShell, but that would be an unnecessary headache. You'd have to do something like this
echo 'C:\search Dir1' 'C:\search Dir2' | Get-ChildItem | Select-String ((Get-Content C:\searchlist.txt) -join '|')
but excluding binary files would be a pain, because AFAIK there's no built-in way to check whether a file is text or binary. If you can rely on the extension, you could add -Filter *.txt after Get-ChildItem.
Bottom line: It's not worth it. Select-String is more versatile in terms of matching patterns, because you can use .NET regular expressions, but if the patterns you want to find are within findstr's limited regex capabilities, you're better off using findstr for this task, and your scripts will be portable because it's always included in Windows.