Using powershell to execute cmd commands - powershell

I love Linux's terminal. I found a package manager for windows called "Chocolatey" and thought if I combined that and powershell I might just have an alternative to the Linux terminal for windows. However, after installing packages I've found that I can't run them from Power Shell. I can get some of them to work using: & "mycommand"
There are a lot of obvious advantages to using Power Shell over CMD. Little things like "ls" instead of "dir" for example. I would really like to just be able to run cmd commands from power shell and hopefully without extra characters. Is there anyway to do this cleanly?

In Powershell, dir and ls are just aliases to the cmdlet Get-ChildItem
You can add alias with the cmdlet : new-Alias
For example, if you want to add an "grep" alias from the cmdlet Select-String you can run :
New-Alias -name grep -Value Select-String
Powershell can run external executable, even without the &, as long as the executable is located in your PATH environment variable.
Are your external commands located in your PATH ?
To check that, run :
$env:PATH
If not, you can add a path to your PATH environment variable, like so :
$ENV:PATH += ";C:\Path\To\YourPackages\"

Related

The term 'oh-my-posh' is not recognized as a name of a cmdlet

I have configured oh-my-posh to be working on powershell and all is working as expected if I run powershell from windows terminal (which is what the document say clearly)
However I tend to run powershell from my WSL terminal as I have alias like this
psl='/mnt/c/Program\ Files/PowerShell/7/pwsh.exe'
but now when I run that alias I got the following error
oh-my-posh: C:\Users\username\OneDrive\Documents\PowerShell\Microsoft.PowerShell_profile.ps1:19
Line |
19 | oh-my-posh init pwsh --config 'C:\Users\username\OneDrive\Documents\Powe …
| ~~~~~~~~~~
| The term 'oh-my-posh' is not recognized as a name of a cmdlet, function, script file, or executable program. Check the spelling of the
| name, or if a path was included, verify that the path is correct and try again
Any idea ?
Thanks
I tried to change the path but it seems the terminal is not recognize the oh-my-posh
On Windows, validate the location of the executable using Get-Command oh-my-posh and add that to the PATH when starting PowerShell, preferably by adding that to your $PROFILE.
$env:Path += ";/mnt/c/Program\ Files/exact/location/oh-my-posh.exe"
That said, it's discouraged to use the Windows version of oh-my-posh on WSL as that will be slower than a native linux build. Same goes for the Windows version of PowerShell.

Executing scripts is the same as dot sourcing?

I saw some surprising behavior in powershell recently.
Consider the script c:\scripts\tst1.ps:
Set-location c:\
Now from powershell:
C:\scripts PS> .\tst1.ps1
C:\ PS>
Why does the calling shell change to “C:\” according to “set-location”? shouldnt the “set-location” run from a subshell according to normal scripting rules for other shells like bash?
I thought that you had to “dot source” the script to get this type of behavior??? That is: “. .\tst1.ps1”? What is happening here.
is my powershell misconfigured on my host computer or is this the actual behavior of powershell these days?
Is there a way to reconfigure powershell to get the old behavior that I expect that is similar to bash shell where the script runs in a sub shell and exits and the current directory is uneffected?
You can run your script with the new instance of powershell:
C:\scripts PS> powershell .\tst1.ps1

How to call msys2 find command from PowerShell with correct shell escape characters?

I'm wondering how can I escape the following command from PowerShell so that it works?
PS C:\Users\buster\Documents\> find -name \*.c
PowerShell says: error not found *.c
PS C:\Users\buster\Documents\> find -name *.c
PowerShell says: error not found *.c
If you used find like that (without the full path) you most likely used the find.exe that ships with Windows (C:\Windows\system32\find.exe), which is more akin to grep than to Unix find. You get that behavior because Windows searches all directories in $env:PATH for files with the given name (and one of the extensions listed in $env:PATHEXT if no extension was specified), and executes the first match. Since %windir%\system32 is usually at the beginning of the PATH, executables from there take precedence.
You could add C:\msys64\msys64\usr\bin to the beginning of the PATH (before %windir%\system32), although I wouldn't recommend that. A better way would be to define an alias for the command:
New-Alias -Name 'find' -Value 'C:\msys64\msys64\usr\bin\find.exe'
Aliases take precedence over files. You could put the alias definition in your PowerShell profile so that it's automatically loaded whenever you start PowerShell.
Or you could simply use ls -r -fi '*.c' (short for Get-ChildItem -Recurse -Filter '*.c'), which would be the PowerShell way.
Ok false alarm..
Apparently its a case of windows having an executable with the same name as msys2's find.exe under c:\windows\system32 and the windows command getting higher priority in the path list. After explicitly typing out the full path to the msys64 version of find.exe it works.
PS C:\Users\buster\Documents\> C:\msys64\msys64\usr\bin\find -name \*.c
Also, Turns out there's a better way to find *.c files native to cmd.exe that you can call from powershell like this:
PS C:\Users\buster\Documents\> cmd /c dir /S /B *.v

How To Use A Windows Environment Variable Independent Of Shell?

I have a need within a .bat file to change to a certain directory which is referenced by an environment variable. Something along these lines:
cd %TMP%
And this works fine from Windows CMD shell. However if I try to run the bat within a Powershell terminal window, it appears that the command simply doesn't work. This does though:
cd $Env:TMP
So I'm trying to figure out how to keep things to one .bat file but still allow users to run it under both the CMD prompt and the PS prompt. I can think of some hacky ways to check to see if I'm under CMD (as opposed to PS) but I'd like to know if there's a better solution.
One thing I noticed is that the PROMPT environment variable is present with CMD but not with Powershell but, as I say, that seems a bit hacky and potentially error-prone.
I'm not trying to pad my rep so if this has already been asked and answered, please point me to it. I just want to find something less hacky than trying to figure out which shell the bat is being run in and changing the cd command to suit it.
By the way, since it may make a difference, I'm running under Powershell 4. I could probably use a .cmd file if that would make any difference but I'd be surprised if it did.
EDIT:
I guess maybe I wasn't as clear as I could be. I'm trying to figure out if there's a way to get the value of an environment variable that will work within a .bat file that will work regardless of whether or not the .bat file is run under the cmd shell or the powershell shell.
Running batch files from PowerShell works just fine. However, since the batch files run in a different interpreter (running .\your.bat is basically the same as running cmd /c .\your.bat), changing the working directory via cd %TMP% in the (CMD) child process doesn't change the working directory for the (PowerShell) parent process.
The syntax you use for variables in batch files is always %variable%.
Demonstration:
PS C:\> $PWD.Path
C:\
PS C:\> Get-Content .\test.bat
#echo off
echo before: %CD%
cd %TMP%
echo after: %CD%
PS C:\> .\test.bat
before: C:\
after: C:\Users\me\AppData\Local\Temp
PS C:\> $PWD.Path
C:\
The batch file echoes the path of the current working directory (%CD%) before and after changing the working directory to %TMP%. The working directory of the parent process (PowerShell) remains unchanged ($PWD.Path).

adding cygwin bin directory to powershell path environment variable ... cygwin within powershell

Powershell is great for scripting. But when it comes to everyday use, certain things can be a huge PITA!!
so i thought it would be great if i could do something like this in my profile.ps1:
$env:path = "$($env:path);c:\cygwin\bin"
to get access to utilities like tar, zip, etc... but this doesn't work. The variable looks right when i do:
PS > $env:path
but when i try to do, say,
PS > unzip foo.zip
i get a command not found type error.
WTF PowerShell!?
edit: great answers! I looked at it with fresh eyes this morning and realized that I just needed to spell 'cygwin' correctly! now I don't have to switch back and forth between two consoles. It should be noted for anyone who uses this tip that your path in powershell is evaluated in order - if you put c:\cygwin\bin at the end of the $env:path variable, it will be searched last, so it won't interfere with existing powershell aliases / cmdlets.
It worked for me:
To set your profile:
$command = '$env:path = $env:path + ";C:\Program Files\Notepad++"'
$command | Out-File -FilePath $PROFILE -Append -Encoding UTF8
Or just the current shell:
$env:path = $env:path + ";C:\Program Files\Notepad++"
Using $env:path to add the cygwin bin to PATH should work as long as you are trying to use it in the same Powershell session. If you open a new console or if you close and open Powershell, it will not be persisted. Otherwise, what you are doing should work. Make sure you are indeed adding the correct path. If you want to persist the changes, add the line to your $profile.
Also, try using the Mingw / Msys / Msysgit utils. I find Mingw to be more lightweight than cygwin ( if you are using cygwin just to get some of these utils.)
PowerShell by default is only going to modify its local copy of PATH. When you run an external command, they aren't going to see the local environment variables.
Per this TechNet article, you can fall back to the .NET static method SetEnvironmentVariable to do this at the user level if you want this to be a permanent change:
[Environment]::SetEnvironmentVariable("TestVariable", "Test value.", "User")