Discussion:
[Help-bash] How to make sure always run external command instead of builtin function?
Peng Yu
2018-12-03 22:12:51 UTC
Permalink
Hi,

I currently use this to make sure to always run the external command.
Is it the best way to do so? Thanks.

"$(type -P cmd)" arg1 arg2
--
Regards,
Peng
Eric Blake
2018-12-03 22:29:55 UTC
Permalink
Post by Peng Yu
Hi,
I currently use this to make sure to always run the external command.
Is it the best way to do so? Thanks.
"$(type -P cmd)" arg1 arg2
env cmd arg1 arg2

also works
--
Eric Blake, Principal Software Engineer
Red Hat, Inc. +1-919-301-3266
Virtualization: qemu.org | libvirt.org
Bob Proulx
2018-12-03 23:22:07 UTC
Permalink
Post by Eric Blake
Post by Peng Yu
I currently use this to make sure to always run the external command.
Is it the best way to do so? Thanks.
"$(type -P cmd)" arg1 arg2
env cmd arg1 arg2
also works
There is also another way too:

(exec cmd ...)

As I learned just the other day:

http://lists.gnu.org/archive/html/bug-bash/2018-09/msg00104.html
http://lists.gnu.org/archive/html/bug-bash/2018-09/msg00101.html

Bob
Peng Yu
2018-12-04 02:51:09 UTC
Permalink
Post by Bob Proulx
Post by Eric Blake
Post by Peng Yu
I currently use this to make sure to always run the external command.
Is it the best way to do so? Thanks.
"$(type -P cmd)" arg1 arg2
env cmd arg1 arg2
also works
(exec cmd ...)
http://lists.gnu.org/archive/html/bug-bash/2018-09/msg00104.html
http://lists.gnu.org/archive/html/bug-bash/2018-09/msg00101.html
Bob
This is good. (exec cmd) is faster.

$ ./main_ls.sh
time for ((i=0;i<300;++i))
do
(exec ls)
done > /dev/null

real 0m2.231s
user 0m0.677s
sys 0m1.013s

time for ((i=0;i<300;++i))
do
"$(type -P ls)"
done > /dev/null

real 0m2.742s
user 0m0.830s
sys 0m1.352s
$ cat main_ls.sh
#!/usr/bin/env bash
# vim: set noexpandtab tabstop=2:

set -v
time for ((i=0;i<300;++i))
do
(exec ls)
done > /dev/null

time for ((i=0;i<300;++i))
do
"$(type -P ls)"
done > /dev/null
--
Regards,
Peng
Dennis Williamson
2018-12-04 03:19:05 UTC
Permalink
Post by Peng Yu
Post by Bob Proulx
Post by Eric Blake
Post by Peng Yu
I currently use this to make sure to always run the external command.
Is it the best way to do so? Thanks.
"$(type -P cmd)" arg1 arg2
env cmd arg1 arg2
also works
(exec cmd ...)
http://lists.gnu.org/archive/html/bug-bash/2018-09/msg00104.html
http://lists.gnu.org/archive/html/bug-bash/2018-09/msg00101.html
Bob
This is good. (exec cmd) is faster.
$ ./main_ls.sh
time for ((i=0;i<300;++i))
do
(exec ls)
done > /dev/null
real 0m2.231s
user 0m0.677s
sys 0m1.013s
time for ((i=0;i<300;++i))
do
"$(type -P ls)"
done > /dev/null
real 0m2.742s
user 0m0.830s
sys 0m1.352s
$ cat main_ls.sh
#!/usr/bin/env bash
set -v
time for ((i=0;i<300;++i))
do
(exec ls)
done > /dev/null
time for ((i=0;i<300;++i))
do
"$(type -P ls)"
done > /dev/null
--
Regards,
Peng
You didn't time the env version.
Peng Yu
2018-12-04 04:46:35 UTC
Permalink
On Mon, Dec 3, 2018 at 9:19 PM Dennis Williamson
Post by Dennis Williamson
Post by Peng Yu
Post by Bob Proulx
Post by Eric Blake
Post by Peng Yu
I currently use this to make sure to always run the external command.
Is it the best way to do so? Thanks.
"$(type -P cmd)" arg1 arg2
env cmd arg1 arg2
also works
(exec cmd ...)
http://lists.gnu.org/archive/html/bug-bash/2018-09/msg00104.html
http://lists.gnu.org/archive/html/bug-bash/2018-09/msg00101.html
Bob
This is good. (exec cmd) is faster.
$ ./main_ls.sh
time for ((i=0;i<300;++i))
do
(exec ls)
done > /dev/null
real 0m2.231s
user 0m0.677s
sys 0m1.013s
time for ((i=0;i<300;++i))
do
"$(type -P ls)"
done > /dev/null
real 0m2.742s
user 0m0.830s
sys 0m1.352s
$ cat main_ls.sh
#!/usr/bin/env bash
set -v
time for ((i=0;i<300;++i))
do
(exec ls)
done > /dev/null
time for ((i=0;i<300;++i))
do
"$(type -P ls)"
done > /dev/null
--
Regards,
Peng
You didn't time the env version.
I assume that it is slower as involves an extra external command 'env'.
--
Regards,
Peng
Pierre Gaston
2018-12-04 07:29:03 UTC
Permalink
Post by Peng Yu
On Mon, Dec 3, 2018 at 9:19 PM Dennis Williamson
Post by Dennis Williamson
Post by Peng Yu
Post by Bob Proulx
Post by Eric Blake
Post by Peng Yu
I currently use this to make sure to always run the external
command.
Post by Dennis Williamson
Post by Peng Yu
Post by Bob Proulx
Post by Eric Blake
Post by Peng Yu
Is it the best way to do so? Thanks.
"$(type -P cmd)" arg1 arg2
env cmd arg1 arg2
also works
(exec cmd ...)
http://lists.gnu.org/archive/html/bug-bash/2018-09/msg00104.html
http://lists.gnu.org/archive/html/bug-bash/2018-09/msg00101.html
Bob
This is good. (exec cmd) is faster.
$ ./main_ls.sh
time for ((i=0;i<300;++i))
do
(exec ls)
done > /dev/null
real 0m2.231s
user 0m0.677s
sys 0m1.013s
time for ((i=0;i<300;++i))
do
"$(type -P ls)"
done > /dev/null
real 0m2.742s
user 0m0.830s
sys 0m1.352s
$ cat main_ls.sh
#!/usr/bin/env bash
set -v
time for ((i=0;i<300;++i))
do
(exec ls)
done > /dev/null
time for ((i=0;i<300;++i))
do
"$(type -P ls)"
done > /dev/null
--
Regards,
Peng
You didn't time the env version.
I assume that it is slower as involves an extra external command 'env'.
--
Regards,
Peng
Maybe, maybe not, env is most likely not forking again, so :

* (exec ls): you have probably a fork and an exec.
* env ls: you have probably a fork an exec and then another exec.

The expensive operation is (I assume) forking so the results may not be so
different..in fact:

$ cat envexec
time for ((i=0;i<300;++i))
do
(exec ls)
done > /dev/null

time for ((i=0;i<300;++i))
do
env ls
done > /dev/null

$ bash envexec

real 0m1,140s
user 0m0,272s
sys 0m0,232s

real 0m1,075s
user 0m0,020s
sys 0m0,072s
Peng Yu
2018-12-04 12:59:54 UTC
Permalink
Post by Pierre Gaston
Post by Peng Yu
On Mon, Dec 3, 2018 at 9:19 PM Dennis Williamson
Post by Dennis Williamson
Post by Peng Yu
Post by Bob Proulx
Post by Eric Blake
Post by Peng Yu
I currently use this to make sure to always run the external command.
Is it the best way to do so? Thanks.
"$(type -P cmd)" arg1 arg2
env cmd arg1 arg2
also works
(exec cmd ...)
http://lists.gnu.org/archive/html/bug-bash/2018-09/msg00104.html
http://lists.gnu.org/archive/html/bug-bash/2018-09/msg00101.html
Bob
This is good. (exec cmd) is faster.
$ ./main_ls.sh
time for ((i=0;i<300;++i))
do
(exec ls)
done > /dev/null
real 0m2.231s
user 0m0.677s
sys 0m1.013s
time for ((i=0;i<300;++i))
do
"$(type -P ls)"
done > /dev/null
real 0m2.742s
user 0m0.830s
sys 0m1.352s
$ cat main_ls.sh
#!/usr/bin/env bash
set -v
time for ((i=0;i<300;++i))
do
(exec ls)
done > /dev/null
time for ((i=0;i<300;++i))
do
"$(type -P ls)"
done > /dev/null
--
Regards,
Peng
You didn't time the env version.
I assume that it is slower as involves an extra external command 'env'.
--
Regards,
Peng
* (exec ls): you have probably a fork and an exec.
* env ls: you have probably a fork an exec and then another exec.
$ cat envexec
time for ((i=0;i<300;++i))
do
(exec ls)
done > /dev/null
time for ((i=0;i<300;++i))
do
env ls
done > /dev/null
$ bash envexec
real 0m1,140s
user 0m0,272s
sys 0m0,232s
real 0m1,075s
user 0m0,020s
sys 0m0,072s
In my case, it can be slower.

time for ((i=0;i<300;++i))
do
(exec ls)
done > /dev/null

real 0m2.104s
user 0m0.663s
sys 0m0.950s

time for ((i=0;i<300;++i))
do
env ls
done > /dev/null

real 0m4.491s
user 0m1.074s
sys 0m2.329s
--
Regards,
Peng
Loading...