• the usage of env

    From [email protected]@21:1/5 to All on Fri Jul 19 14:20:01 2024
    Hello list,

    I am not sure how 'env' command works.

    for example, what's the difference between '/usr/bin/perl' and 'env
    perl' ?

    I know env may set a environment variable in system, so my question also includes:

    1. where to see a shell environment variable? I tried 'echo $ENV'
    showing nothing.

    2. then I tried the following one-line perl to search for 'perl'
    environment variable.

    $ perl -le 'for( keys %ENV ){print "$_ --> $ENV{$_}"}' |grep perl
    _ --> /usr/bin/perl

    the key for perl is "_" in environment variable? under this key, why
    'env perl' just works?

    Thanks for your help.

    regards.
    timothy

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Greg Wooledge@21:1/5 to [email protected] on Fri Jul 19 14:20:01 2024
    On Fri, Jul 19, 2024 at 20:12:14 +0800, [email protected] wrote:
    for example, what's the difference between '/usr/bin/perl' and 'env
    perl' ?

    "env perl" searches your $PATH.

    I know env may set a environment variable in system, so my question also includes:

    env is used to *display* the current shell environment, or to set a new environment for *one* specific process.

    E.g.

    env FOO=bar ./myprogram

    This launches ./myprogram with the additional environment variable FOO
    set to the value bar.

    1. where to see a shell environment variable? I tried 'echo $ENV'
    showing nothing.

    Just run env with no arguments.

    the key for perl is "_" in environment variable? under this key, why
    'env perl' just works?

    The _ environment variable is weird. Please ignore it for now. You
    can live a full and happy life without ever worrying about it.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Thomas Schmitt@21:1/5 to [email protected] on Fri Jul 19 14:50:01 2024
    Hi,

    [email protected] wrote:
    I am not sure how 'env' command works.

    Read the output of

    man env


    for example, what's the difference between '/usr/bin/perl' and 'env perl' ?

    Reading the man page i'd say it's the same difference as between "/usr/bin/perl" and "perl". I.e. the former runs explicitely a particular program file, whereas the latter runs a program file which the shell
    picks for you, depending on the setting of the PATH variable.

    echo "$PATH"


    I know env may set a environment variable in system,

    Not "in system", but for the particular program run which gets started by "env". "man env" says:

    SYNOPSIS
    env [OPTION]... [-] [NAME=VALUE]... [COMMAND [ARG]...]

    DESCRIPTION
    Set each NAME to VALUE in the environment and run COMMAND.

    The NAME=VALUE pairs will be in effect only as long as "env" and the
    started program run.


    (In a bash shell, the main advantages over plain
    [NAME=VALUE]... [COMMAND [ARG]...]
    are probably the env option -i, which disables all inherited exported variables, and -u which disables a particular inherited variable.)


    so my question also includes:
    1. where to see a shell environment variable? I tried 'echo $ENV'
    showing nothing.

    If you want to see all exported variables:

    env

    because the statement in "man env":

    If no COMMAND, print the resulting environment.

    Example shell session (with prompt "$"):

    $ export x=X
    $ y=Y
    $ echo "$x"
    X
    $ echo "$y"
    Y
    $ env | grep '^[xy]='
    x=X
    $

    The not exported variale "y" does not show up in env's output.


    why 'env perl' just works?

    Program "env" (or its helpers) finds a program file with name "perl"
    in one of the directories which are listed in $PATH.


    Have a nice day :)

    Thomas

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Michel Verdier@21:1/5 to [email protected] on Fri Jul 19 15:10:01 2024
    On 2024-07-19, [email protected] wrote:

    $ perl -le 'for( keys %ENV ){print "$_ --> $ENV{$_}"}' |grep perl
    _ --> /usr/bin/perl

    the key for perl is "_" in environment variable? under this key, why
    'env perl' just works?

    Perl $_ is the current (unnamed) value of your loop "for". You could
    write it like this:
    foreach my $key (keys %ENV) { print "$key=$ENV{$key}" }

    https://perldoc.perl.org/variables

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From The Wanderer@21:1/5 to Michel Verdier on Fri Jul 19 15:40:01 2024
    This is an OpenPGP/MIME signed message (RFC 4880 and 3156)
    On 2024-07-19 at 09:02, Michel Verdier wrote:

    On 2024-07-19, [email protected] wrote:

    $ perl -le 'for( keys %ENV ){print "$_ --> $ENV{$_}"}' |grep perl
    _ --> /usr/bin/perl

    the key for perl is "_" in environment variable? under this key, why
    'env perl' just works?

    Perl $_ is the current (unnamed) value of your loop "for". You could
    write it like this:
    foreach my $key (keys %ENV) { print "$key=$ENV{$key}" }

    https://perldoc.perl.org/variables

    I think the question was not about the '$_' variable in the perl
    expression, but about the '_' variable in the output, which in this case contains the full path to the 'perl' binary.

    $ env | grep ^_
    _=/usr/bin/env

    That appears to be a (shell?) environment variable. Greg commented on
    it, as being a weird thing that you will probably never need to worry
    about. I have done some experimenting with it, and it appears to hold
    the equivalent of argv[0] for the command line which invoked the current process - but the logic for determining what that is may well not be
    intuitive for many people.

    'echo $_' produces the full path to 'echo'.

    'sh /tmp/testme' (where that file is a '#!/bin/sh' script which runs
    'echo $_') produces the full path to 'sh'.

    'bash /tmp/testme' (with the script shebang line still pointing to
    /bin/sh) produces the full path to 'bash'.

    'chmod +x /tmp/testme' followed by '/tmp/testme' produces '/tmp/testme'.


    All in all, I think I agree with Greg's description.

    --
    The Wanderer

    The reasonable man adapts himself to the world; the unreasonable one
    persists in trying to adapt the world to himself. Therefore all
    progress depends on the unreasonable man. -- George Bernard Shaw


    -----BEGIN PGP SIGNATURE-----

    iQIzBAEBCgAdFiEEJCOqsZEc2qVC44pUBKk1jTQoMmsFAmaaarcACgkQBKk1jTQo MmtEoQ/7BVb3m1ONxRlWhrsYTz+MM0LpH19hn08bSPQfVJ6qB5sS4/DEjXAF5wl8 aScw8nR1ACNoEEQE1cOoN3GyGC8HefqKNjtohdAaE6oiIYN758DwrtDimAluXNSm casRx5YgKaETWkrZCkB2uV2ZXaHbAqkssD3StZiPoldXj+bIZNwl07kANga7A9/4 sxhwjQyaH3rzd67suFNzWCoWSnjsft9FS3fpX5UwdgaMIeW+ItIssLxYyq53kHCc r5jv9IRXAHQhJP09+kB6Ik+UIE7Xq6UqZXZA9aHxiAnFfBlUxEicCg/gKG7k+N7e WjU39cdVacJ/tts2R2qKbWB+JP9iKclMnf5VjqXW90/s39xdn0eyormuPpDjLCGJ m3QYcox/bxAr2Z1Y1asSBGrmeQmRswM1edQeOGQnO7c5vukSlvlGmoBVcqVBbiUz FoGc6mFTALHpBVqI45fwOHzfjEkxpsPGYGO4WNqaVm7eUrGdFtXWwhuYtD4cIyEX yxRg59/HDeNZACky0etkI5P5GVpjDWJI35DEeCx0CnfFiyalQgvGyG2rBJrdxae9 eLUR2dR8S41DidajkvSaUJzTWA7UyvSgkOHsRdX2YdPsp0KYjwqqkOFYIG/7Trc0 ugGr/PPsNF5W/ZbyzkX9edneo4w/
  • From Greg Wooledge@21:1/5 to [email protected] on Sat Jul 20 00:00:01 2024
    On Sat, Jul 20, 2024 at 05:46:23 +0800, [email protected] wrote:
    $ VAR1=foo && ./a.sh
    $ export VAR2=foo; ./a.sh
    $ ./b.sh


    $VAR1 will be seen by a.sh only, but $VAR2 can be seen my current login session (such as b.sh). Am I right? I am a bit confused about env scope.

    If we assume NO other commands have been executed in this shell so far,
    then:

    VAR1 is not marked for export. It's just a regular shell variable.
    It won't be seen by either call to ./a.sh which is a (non-subshell)
    child process, not will it be seen by ./b.sh which is also a non-subshell child.

    VAR2 is marked for export by the interactive shell. It's a permanent
    part of the shell's environment and will be seen by all child processes
    from that point forward.

    VAR2 will therefore be seen by the second call to ./a.sh and the call
    to ./b.sh.

    Now, what you didn't ask, but what I *expected* you to ask, is:

    What's the difference between these two commands?
    VAR3=foo ./a.sh
    VAR3=bar; ./a.sh

    In the first command, VAR3 is placed in the environment of the command
    being executed. ./a.sh will see it. VAR3 will not survive beyond
    this command. It will be discarded, and future commands will not be
    aware it ever existed.

    In the second command, VAR3 is created as a regular variable in the
    current shell, but not exported to the environment. It will NOT be
    seen by ./a.sh, but it WILL be seen by future shell commands within
    this session.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From [email protected]@21:1/5 to Mike Castle on Fri Jul 19 23:50:01 2024
    On 2024-07-20 00:07, Mike Castle wrote:
    In addition to what everyone else has said about env(1), there is the
    fact that Korn derived shells also supports some of the same features.

    env VAR1=foo VAR2=bar random-command
    VAR1=foo VAR2=bar random-command


    $ VAR1=foo && ./a.sh
    $ export VAR2=foo; ./a.sh
    $ ./b.sh


    $VAR1 will be seen by a.sh only, but $VAR2 can be seen my current login
    session (such as b.sh). Am I right? I am a bit confused about env scope.

    Thanks for your kind help.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From [email protected]@21:1/5 to Greg Wooledge on Sat Jul 20 00:20:01 2024
    On 2024-07-20 05:56, Greg Wooledge wrote:
    On Sat, Jul 20, 2024 at 05:46:23 +0800, [email protected] wrote:
    $ VAR1=foo && ./a.sh
    $ export VAR2=foo; ./a.sh
    $ ./b.sh


    $VAR1 will be seen by a.sh only, but $VAR2 can be seen my current
    login
    session (such as b.sh). Am I right? I am a bit confused about env
    scope.

    If we assume NO other commands have been executed in this shell so far,
    then:

    VAR1 is not marked for export. It's just a regular shell variable.
    It won't be seen by either call to ./a.sh which is a (non-subshell)
    child process, not will it be seen by ./b.sh which is also a
    non-subshell
    child.

    VAR2 is marked for export by the interactive shell. It's a permanent
    part of the shell's environment and will be seen by all child processes
    from that point forward.

    VAR2 will therefore be seen by the second call to ./a.sh and the call
    to ./b.sh.

    I verified that as follows.

    $ VAR=foo ./a.sh
    i can see VAR=foo

    $ ./a.sh
    i can see VAR=

    $ VAR=foo; ./a.sh
    i can see VAR=

    $ export VAR=foo; ./a.sh
    i can see VAR=foo

    Thanks Greg.


    Now, what you didn't ask, but what I *expected* you to ask, is:

    What's the difference between these two commands?
    VAR3=foo ./a.sh
    VAR3=bar; ./a.sh

    In the first command, VAR3 is placed in the environment of the command
    being executed. ./a.sh will see it. VAR3 will not survive beyond
    this command. It will be discarded, and future commands will not be
    aware it ever existed.

    In the second command, VAR3 is created as a regular variable in the
    current shell, but not exported to the environment. It will NOT be
    seen by ./a.sh, but it WILL be seen by future shell commands within
    this session.

    I can not clearly understand for this statement. what's "future shell commands"? can you show an example?

    regards,
    timothy

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Greg Wooledge@21:1/5 to [email protected] on Sat Jul 20 00:30:01 2024
    On Sat, Jul 20, 2024 at 06:17:46 +0800, [email protected] wrote:
    $ VAR=foo ./a.sh
    i can see VAR=foo

    I don't know what "see" means here.

    hobbit:~$ cat a.sh
    #!/bin/sh
    echo "I am a.sh, and inside me, VAR=<$VAR>."
    hobbit:~$ unset -v VAR
    hobbit:~$ VAR=foo ./a.sh
    I am a.sh, and inside me, VAR=<foo>.
    hobbit:~$ echo "VAR=<$VAR>"
    VAR=<>

    VAR is defined in the environment of a.sh but NOT in the calling shell.

    What's the difference between these two commands?
    VAR3=foo ./a.sh
    VAR3=bar; ./a.sh

    In the first command, VAR3 is placed in the environment of the command being executed. ./a.sh will see it. VAR3 will not survive beyond
    this command. It will be discarded, and future commands will not be
    aware it ever existed.

    In the second command, VAR3 is created as a regular variable in the
    current shell, but not exported to the environment. It will NOT be
    seen by ./a.sh, but it WILL be seen by future shell commands within
    this session.

    I can not clearly understand for this statement. what's "future shell commands"? can you show an example?

    hobbit:~$ unset -v VAR
    hobbit:~$ VAR=bar; ./a.sh
    I am a.sh, and inside me, VAR=<>.
    hobbit:~$ echo "VAR=<$VAR>"
    VAR=<bar>

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From [email protected]@21:1/5 to Greg Wooledge on Sat Jul 20 00:40:02 2024
    On 2024-07-20 06:25, Greg Wooledge wrote:

    I can not clearly understand for this statement. what's "future shell
    commands"? can you show an example?

    hobbit:~$ unset -v VAR
    hobbit:~$ VAR=bar; ./a.sh
    I am a.sh, and inside me, VAR=<>.
    hobbit:~$ echo "VAR=<$VAR>"
    VAR=<bar>

    OK I know that. $VAR can be seen by future shell command in this
    session, but cannot be seen by a sub-shell such as a.sh.

    Thanks.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From [email protected]@21:1/5 to Greg Wooledge on Sat Jul 20 00:50:01 2024
    On 2024-07-20 06:35, Greg Wooledge wrote:
    On Sat, Jul 20, 2024 at 06:30:42 +0800, [email protected] wrote:
    On 2024-07-20 06:25, Greg Wooledge wrote:

    I can not clearly understand for this statement. what's "future shell
    commands"? can you show an example?

    hobbit:~$ unset -v VAR
    hobbit:~$ VAR=bar; ./a.sh
    I am a.sh, and inside me, VAR=<>.
    hobbit:~$ echo "VAR=<$VAR>"
    VAR=<bar>

    OK I know that. $VAR can be seen by future shell command in this
    session, but cannot be seen by a sub-shell such as a.sh.

    a.sh is NOT a subshell. That's really super important.

    a.sh is a NON-subshell child process.

    In an actual subshell, you *would* see the variable, because subshells inherit regular variables as well as environment variables.

    hobbit:~$ unset -v VAR
    hobbit:~$ VAR=foo; (echo "I am a subshell, and VAR=<$VAR>")
    I am a subshell, and VAR=<foo>
    hobbit:~$ ./a.sh
    I am a.sh, and inside me, VAR=<>.

    https://mywiki.wooledge.org/SubShell

    make sense now. thanks a lot!

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)