Skip to main content
added 899 characters in body
Source Link
Sergiy Kolodyazhnyy
  • 16.9k
  • 12
  • 58
  • 111

Before we begin discussing $INTEGER type of variables, we need to understand what they really are and how they differ from environment variables. When it comes to shell, variablesVariables such as $INTEGER are called positional parameters. This is described in the POSIX (Portable Operating System Interface) standard, section 2.1 (emphasis mine):

Notice their description. Positional parameters are meant to appear as things to operate on in front of thea command, i.e. command positional_arg_1 positional_arg_2.... They are meant to be provided by user to tell command what specifically to do. When you do echo 'Hello' 'World', it will print out the Hello and World strings, because these are positional parameters to echo - the things you want echo to operate on. And echo is built in such way that it understands positional parameters as strings to be printed (unless they're one of the optional flags like -n ). If you do this with different command it might not understand what Hello and World is because perhaps it expects a number. Notice that positional parameters are not "inherited" - a child process does not know about positional parameters of the parent unless explicitly passed to the child process. Often you see positional parameters being passed with wrapper scripts - the ones that maybe check for already existing instance of a command or add additional positional parameters to the real command that will be called.

By contrast, environment variables are meant to affect multiple programs. They are environment variables, because they're mostly set outside of the program itself (more on this below). For the most part, there is consensus on whatCertain environment variables are supposed to represent and they'll mean the same to each program.such as HOME variable will mean same to echo or bashPATH orhave specific format, specific meaning, and they'll mean the same to each program. HOME variable will mean same to either external utility like /usr/bin/find or theyour shell ( and consequently to a script you wrote yourself ) - it's the home directory of the username under which process runs. Notice that environmental variables can be used to account for specific command behavior, for instance UID environment variable can be used to check whether the script runs with root privileges or not and branch to specific actions accordingly. Environment variables are inheritable - child processes get copy of parent's environment. See also If processes inherit the parent's environment, why do we need export?

In short, the main distinction is that environment variables are set outside of the command and not meant to be varied (usually), while positional parameters are things that are meant to be processed by the command and they change.

What I've noticed from comments is that you're mixing up terminal and shell, and would really recommend you read about real terminals that once upon a time were physical devices. Nowadays, the "terminal" that we're typically referring to, that window with black background and green text is actually software, a process. Terminal is a program that runs a shell, while shell is also a program but the one that reads what you type in to execute ( that is, if it is interactive shell; non-interactive shells are scripts and sh -c 'echo foo' types of invocations). More on shells here.

This is an important distinction, but also important to recognize that terminal is a program and therefore adheres to the same rules of environment and positional parameters. Your gnome-terminal whenwhen started will look at your SHELL environment variable, and spawn the appropriate default shell for you, unless you specify some other command with -e. Let's say I changed my default shell to ksh - gnome-terminal will then spawn ksh instead of bash. That's also an example of how environment is used by programs. If I explicitly tell gnome-terminal with -e to run specific shell - it will do it, but it won't be permanent. By contrast, environment is meant to be mostly unaltered (more on that later).

And this is where distinction becomes important. In interactive shell, you cannot reference $1, $2, and so forth. The shell that you run already is a process, which was spawned with positional parameters ( for bash login shell is one "...whose first character of argument zero is a -, or one started with the --login option." (reference ) )

Before we begin discussing $INTEGER type of variables, we need to understand what they really are and how they differ from environment variables. When it comes to shell, variables such as $INTEGER are called positional parameters. This is described in the POSIX (Portable Operating System Interface) standard, section 2.1 (emphasis mine):

Notice their description. Positional parameters are meant to appear as things to operate on in front of the command, i.e. command positional_arg_1 positional_arg_2.... They are meant to be provided by user to tell command what specifically to do. When you do echo 'Hello' 'World', it will print out the Hello and World strings, because these are positional parameters to echo - the things you want echo to operate on. And echo is built in such way that it understands positional parameters as strings to be printed (unless they're one of the optional flags like -n ). If you do this with different command it might not understand what Hello and World is because perhaps it expects a number.

By contrast, environment variables are meant to affect multiple programs. They are environment variables, because they're mostly set outside of the program itself (more on this below). For the most part, there is consensus on what environment variables are supposed to represent and they'll mean the same to each program. HOME variable will mean same to echo or bash or find or the shell script you wrote yourself - it's the home directory of the username under which process runs.

In short, the main distinction is that environment variables are set outside of the command and not meant to be varied, while positional parameters are things that are meant to be processed by the command and they change.

What I've noticed from comments is that you're mixing up terminal and shell, and would really recommend you read about real terminals that once upon a time were physical devices. Nowadays, the "terminal" that we're typically referring to, that window with black background and green text is actually software, a process. Terminal is a program that runs shell, while shell is also a program but the one that reads what you type in to execute. More on shells here.

This is an important distinction, but also important to recognize that terminal is a program and therefore adheres to the same rules of environment and positional parameters. Your gnome-terminal when started will look at your SHELL environment variable, and spawn the appropriate default shell for you, unless you specify some other command with -e. Let's say I changed my default shell to ksh - gnome-terminal will then spawn ksh instead of bash. That's also an example of how environment is used by programs. If I explicitly tell gnome-terminal with -e to run specific shell - it will do it, but it won't be permanent. By contrast, environment is meant to be mostly unaltered (more on that later).

And this is where distinction becomes important. In interactive shell, you cannot reference $1, $2, and so forth. The shell that you run already is a process, which was spawned with positional parameters ( for bash login shell is one "...whose first character of argument zero is a -, or one started with the --login option." (reference ) )

Before we begin discussing $INTEGER type of variables, we need to understand what they really are and how they differ from environment variables.Variables such as $INTEGER are called positional parameters. This is described in the POSIX (Portable Operating System Interface) standard, section 2.1 (emphasis mine):

Notice their description. Positional parameters are meant to appear in front of a command, i.e. command positional_arg_1 positional_arg_2.... They are meant to be provided by user to tell command what specifically to do. When you do echo 'Hello' 'World', it will print out the Hello and World strings, because these are positional parameters to echo - the things you want echo to operate on. And echo is built such that it understands positional parameters as strings to be printed (unless they're one of the optional flags like -n ). If you do this with different command it might not understand what Hello and World is because perhaps it expects a number. Notice that positional parameters are not "inherited" - a child process does not know about positional parameters of the parent unless explicitly passed to the child process. Often you see positional parameters being passed with wrapper scripts - the ones that maybe check for already existing instance of a command or add additional positional parameters to the real command that will be called.

By contrast, environment variables are meant to affect multiple programs. They are environment variables, because they're set outside of the program itself (more on this below). Certain environment variables such as HOME or PATH have specific format, specific meaning, and they'll mean the same to each program. HOME variable will mean same to either external utility like /usr/bin/find or your shell ( and consequently to a script ) - it's the home directory of the username under which process runs. Notice that environmental variables can be used to account for specific command behavior, for instance UID environment variable can be used to check whether the script runs with root privileges or not and branch to specific actions accordingly. Environment variables are inheritable - child processes get copy of parent's environment. See also If processes inherit the parent's environment, why do we need export?

In short, the main distinction is that environment variables are set outside of the command and not meant to be varied (usually), while positional parameters are things that are meant to be processed by the command and they change.

What I've noticed from comments is that you're mixing up terminal and shell, and would really recommend you read about real terminals that once upon a time were physical devices. Nowadays, the "terminal" that we're typically referring to, that window with black background and green text is actually software, a process. Terminal is a program that runs a shell, while shell is also a program but the one that reads what you type in to execute ( that is, if it is interactive shell; non-interactive shells are scripts and sh -c 'echo foo' types of invocations). More on shells here.

This is an important distinction, but also important to recognize that terminal is a program and therefore adheres to the same rules of environment and positional parameters. Your gnome-terminal when started will look at your SHELL environment variable, and spawn the appropriate default shell for you, unless you specify some other command with -e. Let's say I changed my default shell to ksh - gnome-terminal will then spawn ksh instead of bash. That's also an example of how environment is used by programs. If I explicitly tell gnome-terminal with -e to run specific shell - it will do it, but it won't be permanent. By contrast, environment is meant to be mostly unaltered (more on that later).

And this is where distinction becomes important. The shell that you run already is a process, which was spawned with positional parameters ( for bash login shell is one "...whose first character of argument zero is a -, or one started with the --login option." (reference ) )

added 6920 characters in body
Source Link
Sergiy Kolodyazhnyy
  • 16.9k
  • 12
  • 58
  • 111

Note on set command

The set command, according to manual behaves like so (from bash manual, emphasis added):

Without options, the name and value of each shell variable are displayed in a format that can be reused as input for setting or resetting the currently-set variables.

In other words set looks at variables specific to shell, some of which happen to be in the environment, for example HOME. By contrast commands like env and printenv look at actual environment variable with which a command runs. See also this.


Note on set command

The set command, according to manual behaves like so (from bash manual, emphasis added):

Without options, the name and value of each shell variable are displayed in a format that can be reused as input for setting or resetting the currently-set variables.

In other words set looks at variables specific to shell, some of which happen to be in the environment, for example HOME. By contrast commands like env and printenv look at actual environment variable with which a command runs. See also this.

added 6920 characters in body
Source Link
Sergiy Kolodyazhnyy
  • 16.9k
  • 12
  • 58
  • 111

Environment Variables vs Positional Parameters

NoBefore we begin discussing $INTEGER type of variables, they're notwe need to understand what they really are and how they differ from environment variables. When it comes to shell, they're calledvariables such as positional parameters and there's reason for$INTEGER are called positional parameters. This is described in the differencePOSIX (Portable Operating System Interface) standard, section 2.1 (emphasis mine): there's

  1. The shell executes a function (see Function Definition Command), built-in (see Special Built-In Utilities), executable file, or script, giving the names of the arguments as positional parameters numbered 1 to n, and the name of the command (or in the case of a function within a script, the name of the script) as the positional parameter numbered 0 (see Command Search and Execution).

By contrast, variables such as $HOME and $PATH are environment variables. Their definition is described in which command can operate (isection 8 of the standard:

Environment variables defined in this chapter affect the operation of multiple utilities, functions, and applications. There are other environment variables that are of interest only to specific utilities. Environment variables that apply to a single utility only are defined as part of the utility description.

Notice their description. Positional parameters are meant to appear as things to operate on in front of the command, i.e. certain conditions and restrictions) and that shouldcommand positional_arg_1 positional_arg_2.... They are meant to be availableprovided by user to all programs; then there'stell command what user must providespecifically to do. That's why they're not on theWhen you do setecho 'Hello' 'World' list -, it will print out the $1Hello and $2World strings, because these are specificpositional parameters to each instance of nonecho -interactive shell the things you runwant echo to operate on. And echo is built in such way that it understands positional parameters as strings to be printed ( noticeunless they're one of the "non-interactive" part, which meansoptional flags like -n ). If you can usedo this with different command it might not understand what $1Hello in shell scripts and sh -c 'command 1; command 2World typeis because perhaps it expects a number.

By contrast, environment variables are meant to affect multiple programs. They are environment variables, because they're mostly set outside of thingsthe program itself (more on this below). Of courseFor the most part, there is consensus on what environment variables are wayssupposed to represent and they'll mean the same to each program. set them other wiseHOME variable will mean same to echo or bash or find or the shell script you wrote yourself - it's the home directory of the username under which process runs.

In short, as well asthe main distinction is that environment variables are set outside of the command and not meant to be varied, while positional parameters are things that are meant to be processed by the command and they change.


Not just shell concepts

What I've noticed from comments is that you're mixing up terminal and shell, and would really recommend you read about real terminals that once upon a time were physical devices. Nowadays, the list"terminal" that we're typically referring to, that window with black background and green text is actually software, a process. Terminal is a program that runs shell, while shell is also a program but the one that reads what you type in to execute. More on shells here.

This is an important distinction, but also important to recognize that terminal is a program and therefore adheres to the same rules of thoseenvironment and positional parameters via. Your shiftgnome-terminal when started will look at your SHELL environment variable, and spawn the appropriate default shell for you, unless you specify some other command with -e. Let's say I changed my default shell to ksh - gnome-terminal will then spawn ksh instead of bash. That's also an example of how environment is used by programs. If I explicitly tell gnome-terminal with -e to run specific shell - it will do it, but theit won't be permanent. By contrast, environment and positional variables as I've explained already have somewhat different purposeis meant to be mostly unaltered (more on that later).

Take for instanceSo as you can see, environment and positional variables are both properties of a process/command, not just shell. When it comes to shell scripts, they also follow the model that was set by C programming language. The mainTake for instance the C main function which typically looks like

, where argc is number of command-line arguments and argv is effectively array of command-line parameters, and then there's environ function ( on Linux that's man -e 7 environ ) to access things like user's home directory path, list of directories in PATH where we can look for executables, etc. Shell scripts are also modeled in the similar way. In shell terminology, we have positional parameters $1, $2 and so forth, while $# is number of positional parameters. What about $0 ? That's the name of the executable itself, which is again also modeled from C programming language - argv[0] would be name of your C "executable". And this is fairly true for most programming and scripting languages.

Interactive vs Non-interactive shells

One of the things I've already hinted is the distinction between interactive and non-interactive shells. The prompt where you type in commands - that's interactive, it interacts with the user. By contrast when you have a shell script or you run bash -c'' that's non-interactive.

And this is where distinction becomes important. In interactive shell, you cannot reference $1, $2, and so forth. The shell that you run already is a process, which was spawned with positional parameters ( for bash login shell is one "...whose first character of argument zero is a -, or one started with the --login option." (reference ) )

By contrast, scripts and shells launched with -c option can take advantage of $1 and $2 arguments. For instance,

$ bash -c 'echo $1; stat $2' sh 'Hello World' /etc/passwd
Hello World
  File: '/etc/passwd'
  Size: 2913        Blocks: 8          IO Block: 4096   regular file
Device: 801h/2049d  Inode: 6035604     Links: 1
Access: (0644/-rw-r--r--)  Uid: (    0/    root)   Gid: (    0/    root)
Access: 2017-08-12 14:48:37.125879962 -0600
Modify: 2017-08-12 14:48:37.125879962 -0600
Change: 2017-08-12 14:48:37.137879811 -0600
 Birth: -

Notice that I've also used sh there, because small quirk of -c option is to take first positional parameter and assign it to $0, unlike typically being a name of the program.

Another thing that is important to notice is that positional parameters are what I call "framable". Notice how, we first launched bash with its own positional parameters, but those positional parameters became parameters to echo and stat. And each program understands it in its own way. If we gave to stat a string Hello World and there's no file Hello World it would produce an error; bash treats it just as a simple string but stat expects that string to be an existing filename. By contrast, all programs would agree that environment variable HOME is a directory ( unless the programmer coded it in an unreasonable way).


Can we mess around with environment variables and positional parameters ?

Technically, we can mess around with both, but we shouldn't mess around with environment variables, while we often have to provide positional parameters. We can run commands in shell with prepending a variable, for instance:

$ hello=world bash -c 'echo $hello'
world

We can also place variables into environment simply using export variable=value from within shell or script. Or we can run a command with completely empty environment with env -c command arg1 arg2. However, typically it is not recommended to mess around with environment, especially using upper-case variables or overwriting already existing environment variables. Notice that's recommended although not a standard.

For positional parameters, the way to set them is obvious, just prepend them to the command, but also there are ways to set them other wise, as well as change the list of those parameters via shift command.

In conclusion, purpose of these two is different, and they exist for a reason.

Answer is under construction and will be edited, please be patient:) I hope people gained some insight from this answer, and it was fun reading it just as it was for me to write this answer.

No, they're not environment variables, they're called positional parameters and there's reason for the difference: there's environment in which command can operate (i.e. certain conditions and restrictions) and that should be available to all programs; then there's what user must provide. That's why they're not on the set list - $1 and $2 are specific to each instance of non-interactive shell you run ( notice the "non-interactive" part, which means you can use $1 in shell scripts and sh -c 'command 1; command 2 type of things ). Of course there are ways to set them other wise, as well as change the list of those parameters via shift command, but the environment and positional variables as I've explained already have somewhat different purpose.

Take for instance C programming language. The main function typically looks like

, where argc is number of command-line arguments and argv is effectively array of command-line parameters, and then there's environ function ( on Linux that's man -e 7 environ ) to access things like user's home directory path, list of directories in PATH where we can look for executables, etc. Shell scripts are also modeled in the similar way. In shell terminology, we have positional parameters $1, $2 and so forth, while $# is number of positional parameters. What about $0 ? That's the name of the executable itself, which is again also modeled from C programming language - argv[0] would be name of your C "executable". And this is fairly true for most programming and scripting languages.

In conclusion, purpose of these two is different, and they exist for a reason.

Answer is under construction and will be edited, please be patient:)

Environment Variables vs Positional Parameters

Before we begin discussing $INTEGER type of variables, we need to understand what they really are and how they differ from environment variables. When it comes to shell, variables such as $INTEGER are called positional parameters. This is described in the POSIX (Portable Operating System Interface) standard, section 2.1 (emphasis mine):

  1. The shell executes a function (see Function Definition Command), built-in (see Special Built-In Utilities), executable file, or script, giving the names of the arguments as positional parameters numbered 1 to n, and the name of the command (or in the case of a function within a script, the name of the script) as the positional parameter numbered 0 (see Command Search and Execution).

By contrast, variables such as $HOME and $PATH are environment variables. Their definition is described in section 8 of the standard:

Environment variables defined in this chapter affect the operation of multiple utilities, functions, and applications. There are other environment variables that are of interest only to specific utilities. Environment variables that apply to a single utility only are defined as part of the utility description.

Notice their description. Positional parameters are meant to appear as things to operate on in front of the command, i.e. command positional_arg_1 positional_arg_2.... They are meant to be provided by user to tell command what specifically to do. When you do echo 'Hello' 'World', it will print out the Hello and World strings, because these are positional parameters to echo - the things you want echo to operate on. And echo is built in such way that it understands positional parameters as strings to be printed (unless they're one of the optional flags like -n ). If you do this with different command it might not understand what Hello and World is because perhaps it expects a number.

By contrast, environment variables are meant to affect multiple programs. They are environment variables, because they're mostly set outside of the program itself (more on this below). For the most part, there is consensus on what environment variables are supposed to represent and they'll mean the same to each program. HOME variable will mean same to echo or bash or find or the shell script you wrote yourself - it's the home directory of the username under which process runs.

In short, the main distinction is that environment variables are set outside of the command and not meant to be varied, while positional parameters are things that are meant to be processed by the command and they change.


Not just shell concepts

What I've noticed from comments is that you're mixing up terminal and shell, and would really recommend you read about real terminals that once upon a time were physical devices. Nowadays, the "terminal" that we're typically referring to, that window with black background and green text is actually software, a process. Terminal is a program that runs shell, while shell is also a program but the one that reads what you type in to execute. More on shells here.

This is an important distinction, but also important to recognize that terminal is a program and therefore adheres to the same rules of environment and positional parameters. Your gnome-terminal when started will look at your SHELL environment variable, and spawn the appropriate default shell for you, unless you specify some other command with -e. Let's say I changed my default shell to ksh - gnome-terminal will then spawn ksh instead of bash. That's also an example of how environment is used by programs. If I explicitly tell gnome-terminal with -e to run specific shell - it will do it, but it won't be permanent. By contrast, environment is meant to be mostly unaltered (more on that later).

So as you can see, environment and positional variables are both properties of a process/command, not just shell. When it comes to shell scripts, they also follow the model that was set by C programming language. Take for instance the C main function which typically looks like

, where argc is number of command-line arguments and argv is effectively array of command-line parameters, and then there's environ function ( on Linux that's man -e 7 environ ) to access things like user's home directory path, list of directories in PATH where we can look for executables, etc. Shell scripts are also modeled in the similar way. In shell terminology, we have positional parameters $1, $2 and so forth, while $# is number of positional parameters. What about $0 ? That's the name of the executable itself, which is again also modeled from C programming language - argv[0] would be name of your C "executable". And this is fairly true for most programming and scripting languages.

Interactive vs Non-interactive shells

One of the things I've already hinted is the distinction between interactive and non-interactive shells. The prompt where you type in commands - that's interactive, it interacts with the user. By contrast when you have a shell script or you run bash -c'' that's non-interactive.

And this is where distinction becomes important. In interactive shell, you cannot reference $1, $2, and so forth. The shell that you run already is a process, which was spawned with positional parameters ( for bash login shell is one "...whose first character of argument zero is a -, or one started with the --login option." (reference ) )

By contrast, scripts and shells launched with -c option can take advantage of $1 and $2 arguments. For instance,

$ bash -c 'echo $1; stat $2' sh 'Hello World' /etc/passwd
Hello World
  File: '/etc/passwd'
  Size: 2913        Blocks: 8          IO Block: 4096   regular file
Device: 801h/2049d  Inode: 6035604     Links: 1
Access: (0644/-rw-r--r--)  Uid: (    0/    root)   Gid: (    0/    root)
Access: 2017-08-12 14:48:37.125879962 -0600
Modify: 2017-08-12 14:48:37.125879962 -0600
Change: 2017-08-12 14:48:37.137879811 -0600
 Birth: -

Notice that I've also used sh there, because small quirk of -c option is to take first positional parameter and assign it to $0, unlike typically being a name of the program.

Another thing that is important to notice is that positional parameters are what I call "framable". Notice how, we first launched bash with its own positional parameters, but those positional parameters became parameters to echo and stat. And each program understands it in its own way. If we gave to stat a string Hello World and there's no file Hello World it would produce an error; bash treats it just as a simple string but stat expects that string to be an existing filename. By contrast, all programs would agree that environment variable HOME is a directory ( unless the programmer coded it in an unreasonable way).


Can we mess around with environment variables and positional parameters ?

Technically, we can mess around with both, but we shouldn't mess around with environment variables, while we often have to provide positional parameters. We can run commands in shell with prepending a variable, for instance:

$ hello=world bash -c 'echo $hello'
world

We can also place variables into environment simply using export variable=value from within shell or script. Or we can run a command with completely empty environment with env -c command arg1 arg2. However, typically it is not recommended to mess around with environment, especially using upper-case variables or overwriting already existing environment variables. Notice that's recommended although not a standard.

For positional parameters, the way to set them is obvious, just prepend them to the command, but also there are ways to set them other wise, as well as change the list of those parameters via shift command.

In conclusion, purpose of these two is different, and they exist for a reason. I hope people gained some insight from this answer, and it was fun reading it just as it was for me to write this answer.

added 151 characters in body
Source Link
Sergiy Kolodyazhnyy
  • 16.9k
  • 12
  • 58
  • 111
Loading
Source Link
Sergiy Kolodyazhnyy
  • 16.9k
  • 12
  • 58
  • 111
Loading