ChatGPT解决这个技术问题 Extra ChatGPT

Can I get "&&" or "-and" to work in PowerShell?

&& is notoriously hard to search for on Google Search, but the best I've found is this article which says to use -and.

Unfortunately it doesn't give any more information, and I can't find out what I'm supposed to do with -and (again, a notoriously hard thing to search for).

The context I'm trying to use it in is "execute cmd1, and if successful, execute cmd2", basically this:

csc /t:exe /out:a.exe SomeFile.cs && a.exe

If you just want to run multiple commands on a single line and you don't care if the first one fails or not, you can use ; For most of my purposes this is fine.

For example: kill -n myapp; ./myapp.exe.

PowerShell has -and and -or logical operators. Are the operators not working the way you expect them to? If so, you can post the expression here.
See this question, it does what you want: stackoverflow.com/questions/1917271/…
Regarding the need to perform web searches for queries with literal (and significant) symbols: SymbolHound is useful for this. Here are some examples that pertain to the question: powershell &&; powershell -and. If you use DuckDuckGo, you can search SymbolHound via !sym.
June 2019 update: PowerShell team are implementing && and ||! Weigh in at the GitHub PR
From PowerShell 7, && and || are implemented. They are called "pipeline chain operators". docs.microsoft.com/en-us/powershell/module/…

J
Jay Bazuzi

In CMD, '&&' means "execute command 1, and if it succeeds, execute command 2". I have used it for things like:

build && run_tests

In PowerShell, the closest thing you can do is:

(build) -and (run_tests)

It has the same logic, but the output text from the commands is lost. Maybe it is good enough for you, though.

If you're doing this in a script, you will probably be better off separating the statements, like this:

build
if ($?) {
    run_tests
}

2019/11/27: The &&operator is now available for PowerShell 7 Preview 5+:

PS > echo "Hello!" && echo "World!"
Hello!
World!


RE: "ridiculous that they would remove" - I don't like to think of PowerShell as "CMD with the stupid parts removed". is.gd/k92B
I don't like to think of PowerShell as "CMD with the stupid parts removed". I like to think of it as "Bash without any of the useful bits".
You can also do build ; if ($?) { run_tests } on the command line too.
The quickest way to real frustration when learning PowerShell is to start by thinking that it is just an expanded CMD or bash. It has a fundamentally different model, epecially when it comes to input, output, piping, and results. Start with a good tutorial or overview, and don't try too hard to make syntax from other shells work. You have to take it on its own terms.
Taking PowerShell on its own terms, how do I run a command and then, only if that command succeeds, run another command? I don't think that's imposing bash ideas on PowerShell. It's basic shell functionality. So far the best I've seen is build ; if ($?) { run_tests } which I'll be using from now on. I hope the PowerShell team adds && support!
B
BoltClock

&& and || were on the list of things to implement (still are) but did not pop up as the next most useful thing to add. The reason is that we have -AND and -OR. If you think it is important, please file a suggestion on Connect and we'll consider it for V3.


I'm signed up on Connect, and have nominated myself for powershell, but I can't figure out how to place a suggestion. The Connect website is really complex and confusing :-(
I couldn't find a pre-existing request so I made one: connect.microsoft.com/PowerShell/feedback/details/778798/…
You know, the question is still how to write an equivalent, and your answer would be a lot more useful if you added an example of using -AND
It's important because it's a basic flow control tool used on systems older than windows for almost eternity. Thus is presents YET ANOTHER breaking difference between linux and windows.
I hope Jeffrey Snover is listening, this SO should be enough reason to implement it by now. It's been too long, and now PowerShell starts to popup in places, like VSCode uses it as a default terminal in Windows. This is total pain without &&, the -and eats the output, not equivalent at all.
I
Ivan

Try this:

$errorActionPreference='Stop'; csc /t:exe /out:a.exe SomeFile.cs; a.exe

Note: If the first command fails the second is still going to run.
Preference variable $ErrorActionPreference only governs how non-terminating errors reported by cmdlets are treated; external utilities such as csc and a.exe never report such errors (they only reflect their exit status in $? (success flag) and $LASTEXITCODE (the specific exit code reported)), so your command line amounts to unconditional execution of both commands (the equivalent of cmd's csc /t:exe /out:a.exe SomeFile.cs & a.exe)
P
Peter Mortensen

If your command is available in cmd.exe (something like python ./script.py, but not PowerShell command like ii . (this means to open the current directory by Windows Explorer)), you can run cmd.exe within PowerShell. The syntax is like this:

cmd /c "command1 && command2"

Here, && is provided by cmd syntax described in this question.


Nice, upgrade to cmd to access it's additional functionality.
P
Peter Mortensen

I tried this sequence of commands in PowerShell:

First Test

PS C:\> $MyVar = "C:\MyTxt.txt"
PS C:\> ($MyVar -ne $null) -and (Get-Content $MyVar)
True

($MyVar -ne $null) returned true and (Get-Content $MyVar) also returned true.

Second Test

PS C:\> $MyVar = $null
PS C:\> ($MyVar -ne $null) -and (Get-Content $MyVar)
False

($MyVar -ne $null) returned false and so far I must assume the (Get-Content $MyVar) also returned false.

The third test proved the second condition was not even analyzed.

PS C:\> ($MyVar -ne $null) -and (Get-Content "C:\MyTxt.txt")
False

($MyVar -ne $null) returned false and proved the second condition (Get-Content "C:\MyTxt.txt") never ran, by returning false on the whole command.


Your are right! this behaves as the && operator. Even a $() on the right side will not let to evaluate this!
F
FranciscoSerrano372

Very old question, but for the newcomers: maybe the PowerShell version (similar but not equivalent) that the question is looking for, is to use -and as follows:

(build_command) -and (run_tests_command)


This may be ok for your use case, but it is not behaving like &&, in that it ignores the exit code of build_command.
This is definitely not doing the correct thing. It will run the second command even if the first one failed.
this is completely wrong. ; is the equivalent to & in cmd and ; in bash. It's definitely not the same as && in cmd
It also mutes STDOUT and STDERR for both processes.
After numerous edits this duplicates the accepted answer stackoverflow.com/a/564092/389424
C
Chris

Just install PowerShell 7 (go here, and scroll and expand the assets section). This release has implemented the pipeline chain operators.


T
TankorSmash

A verbose equivalent is to combine $LASTEXITCODE and -eq 0:

msbuild.exe args; if ($LASTEXITCODE -eq 0) { echo 'it built'; } else { echo 'it failed'; }

I'm not sure why if ($?) didn't work for me, but this one did.


Checking $LASTEXITCODE is indeed the most robust approach, because, unfortunately, $? can yield false negatives with 2> redirections; see this answer.
P
Peter Mortensen

Use:

if (start-process filename1.exe) {} else {start-process filename2.exe}

It's a little longer than "&&", but it accomplishes the same thing without scripting and is not too hard to remember.


Start-Process is the wrong tool to use for invoking command-line utilities in general. Specifically, as used here, Start-Process runs filename1.exe asynchronously in a new console window and returns nothing, which in a Boolean context evaluates to $false. Even if you omitted Start-Process (which is how you should invoke command-line utilities - directly), the approach would fall short, because the outcome of the conditional then depends on whether the utility produced any stdout output, which has no guaranteed relationship with whether it succeeded or not.
P
Peter Mortensen

I think a simple if statement can accomplish this. Once I saw mkelement0's response that the last exit status is stored in $?, I put the following together:

# Set the first command to a variable
$a=somecommand

# Temporary variable to store exit status of the last command (since we can't write to "$?")
$test=$?

# Run the test
if ($test=$true) { 2nd-command }

So for the OP's example, it would be:

a=(csc /t:exe /out:a.exe SomeFile.cs); $test = $?; if ($test=$true) { a.exe }

M
Matt Hamilton

It depends on the context, but here's an example of "-and" in action:

get-childitem | where-object { $_.Name.StartsWith("f") -and $_.Length -gt 10kb }

So that's getting all the files bigger than 10kb in a directory whose filename starts with "f".


This is not an answer to the original question, which is about executing multiple commands.
P
Peter Mortensen

We can try this command instead of using && method:

try {hostname; if ($lastexitcode -eq 0) {ipconfig /all | findstr /i bios}} catch {echo err} finally {}

There is no need for try / catch, because it is only needed for terminating errors, which external utilities such as hostname, ipconfig and findstr cannot trigger. Checking $LASTEXITCODE is only needed if you want to know the specific exit code set by an external utility - abstract success or failure is reflected in $?, just as with native cmdlets.
I think @Cyberiron is on the right track. I think && in Unix is a lot like try/catch in that it doesn't require you to wrap subsequent commands in a new block (i.e. }) when you short-circuit later commands (skip them). I think a AmpAmp function/filter that throws when if (!?) { throw "last command failed" } would be a very useful replacement for porting && to PowerShell. usage: csc /t:exe /out:a.exe SomeFile.cs; AmpAmp; a.exe