Reuse the `apt up` part of the `apt update` and `apt upgrade` commands to execute both in sequence in just one line
How to reuse the apt up
part of the apt update
and apt upgrade
commands to execute both commands in sequence in just one line without an alias.
Something like: apt up{date,grade}
.
Solution 1:
The simple way ( and more efficient) is via for loop (on one line but here it's shown in multiple lines for clarity):
for i in {date,grade}; do
apt up${i}
done
The smart way is to make an alias in ~/.bashrc
for these two commands and forget about retyping it ever again:
alias upgrade=' sudo apt update && sudo apt upgrade'
The elaborate way is to do this:
$ echo sudo" "apt" "up{"date","grade"}" && " :
sudo apt update && sudo apt upgrade && :
See what's happening ? We're building a valid string of text to be run by shell. Now all you need to do is to use eval
instead of echo
. But eval
is generally not recommended in shell scripting and this command is much more convoluted and non portable than the for loop. Variation on the theme without eval (and shortest so far, but not efficient due to pipe and multiple commands echo
,two apt
,sudo
and sh
so lots of forking):
$ echo "apt "{update,upgrade}";"|sudo sh
We can also use set
to turn the desired sequence into positional parameters and just execute apt
with $1
and $2
args:
$ set {update,upgrade}; echo apt $1 && echo apt $2
apt update
apt upgrade
Or alternatively use for loop again, since it defaults to processing positional parameters if you don't specify a sequence in the for variable (sequence)
$ set {update,upgrade} ; for i; do echo apt $i ;done
apt update
apt upgrade
Using set
is a very common technique I see among professionals who work with shells a lot, and for a good reason - this is very portable and will work in /bin/sh
where you have no arrays or {a,b,c}
expansion. So POSIX-ly portable way would be set update upgrade ; for i; do echo apt $i ;done
. Additionally, this should be efficient.
Or we can go the while
loop route:
$ echo {date,$'\n',grade}|while read i;do echo apt up${i}; done
apt update
apt upgrade
Of course remember to run it without echo
for actual command execution to take place
Solution 2:
You can also use bash history expansion to get parts of the current command line and modify it:
$ apt update; !#:s/date/grade
apt update; apt upgrade;
Reading package lists... Done
...
-
!#
is the current line -
:s/date/grade
is a modifier that substitutesdate
withgrade
Solution 3:
Another simple option using xargs
instead of for
:
echo up{dat,grad}e | xargs -n1 apt
Test:
$ echo up{dat,grad}e | xargs -n1 echo apt
apt update
apt upgrade
However, I’d prefer a shell alias just like Sergiy because these “simple” ways are not simple enough to be actually useful.
Solution 4:
Create a function like this:
repeat() {
for suffix in "${@:2}";
do
eval "$1""$suffix";
done
}
Then you can run repeat 'apt up' {date,grade}
. This has the benefit of being reusable for totally different commands, although it's not saving you any typing for this one.
I'd certainly agree with some of the other answers that something like this is probably more useful:
alias apt-up='apt update && apt upgrade'