How can I force MacPorts to upgrade all upgradeable ports that it can?
This is what I use... it might not be pretty but it works:
sudo bash -c 'for port in `port outdated  2&gt;/dev/null |  tail -n +2 | awk '\''{print $1}'\''` ; do echo -n &quot;$port:&quot; ;  port -N upgrade $port 2&gt;&gt; /tmp/upgrade-ports.err &gt;&gt; /tmp/upgrade-ports.out &amp;&amp; echo &quot;✓&quot; || echo &quot;✕&quot; ; done'

Let me brake it down for you:

first, you don't want sudo in a loop, otherwise you need to keep putting your password. To avoid sudo I got the whole loop and quoted it (Alt+' in zsh is very helpful to properly escape the existing quotes) and then ran it with sudo bash -c. Alternatively you can put it in a file and run it as a script with sudo script

that leaves us with this loop:


for port in `port outdated  2&gt;/dev/null | tail -n +2 | awk '{print $1}'` ; do echo -n &quot;$port:&quot; ;  port -N upgrade $port 2&gt;&gt; /tmp/upgrade-ports.err &gt;&gt; /tmp/upgrade-ports.out &amp;&amp; echo &quot;✓&quot; || echo &quot;✕&quot; ; done```


I build the list of ports with:
port outdated  2&gt;/dev/null | tail -n +2 | awk '{print $1}' (tail removes the line &quot;The following installed ports are outdated:&quot;)
for every port I print the port name and a semicolon (without newline )
then I try to upgrade it non interactively, and save the output and errors
if the upgrade was successful I print a &quot;✓&quot; and a newline, otherwise a &quot;✕&quot; and a newline
note that this will not show the dependencies being installed, but you can tail the log to see what is happening*
this is what the output looks like:

adwaita-icon-theme:✓
apr:✕
aquaterm:✓

HTH
*Edited to clarify.
This means that in your example the output would look like this:
A:✕
B:✓
C:✓
D:✓
E:✓
F:✓
G:✓

But B will take a LONG time, and C, D, E and F will be very fast because they have already been upgraded during B.