What does set -a "Mark variables which are modified or created for export" actually mean? - bash

The help text for set -a is somewhat cryptic to me, but maybe i just don't understand what bash is doing behind the scenes with variables. Can someone explain why "marking" variables is needed (what are "unmarked" variables)?

My bash man-page uses a slightly different wording for this: Each variable or function that is created or modified is given the export attribute and marked for export to the environment of subsequent commands. This sounds more clear to me. It means:
Each variable you define in your script, is placed in the environment of any child process you create, and each function you define is also available to each bash-child-process you create.

Related

Setting up default overwritable constructors and destructors or other functions for a set of commands

alias cmd_name="source mainshell cmd_name"
My plan is to alias a single main script to a set of script names. Now on invocation of any script that main script would be called and it can define certain functions or constructors and destructor. Then it can check that script file if it has a constructor definition. If it has one, call that constructor else call the default one. Then source that script and then call the destructor. This would also give that script access to the default functions setup by main script. This shall work fine but these aliases can’t be exported to subshells.
To add to that, I just want these defaults functions available to that particular aliased set of commands and want those functions to destroy once command execution is complete. That’s why I can’t just write them on .bash_profile making it absolutely global.
command_name() {
# initial code
source path/to/command_name
# destructing code
}
Another option which I found was to create function for each name and call my script inside. This one is exportable too. In this way i could just encapsulate every command in a function with same name and can easily have initial codes and destroying code. Here the problem is that i can’t define any more functions inside that function and it would get really clumsy too doing everything inside a function.
Another thought I had was symbolic links, but they seem to have a limit to how many I can create to a particular script.
What should be the best way to achieve this or if its somehow an inappropriate design, can someone please explain?
IIUC you're trying to achieve the following:
A set of commands that necessarily take place in the context of the current shell rather than a new shell process.
These commands have a lot of common functionality that needs to be factored out of these commands.
The common functionality must not be accessible to the current shell.
In that case, the common code would be e.g. functions & variables that you have to explicitly unset after the command has been executed. Therefore, your best bet is to have a function per-command, have that function source the common code, and have the common code also have another function (called before you return) to unset everything.
Notes:
You can actually declare functions inside other functions, but the nested functions will actually be global - so name them uniquely and don't forget to unset them.
If they don't need to affect the current shell then you can just put them in their own file, source the common code, and not unset anything.
There is generally no limit to how many symlinks you can create to a single file. The limit on symlink chains (symlink to symlink to symlink etc.) is low.

How to Make Constants in an Expect Script?

I would like to be able to create and set the value of constants in an Expect script.
In scripts such as Bash and a great many programming languages, one can create and assign a value to a constant. I have tried many online sites looking how to do this in Expect, but I have surprisingly not been able to come across this basic information.
Creating and assigning a variable named name in Bash: name="Bob"
Creating and assigning a constant named CONFIG_FILE in Bash: readonly CONFIG_FILE="Configuration.ini"
Creating and assigning a variable named copyPath in Expect: set copyPath "/home/bob/tmp"
Creating and assigning a constant in Expect: ?????
How does one create and set the value of constants in an Expect script?
Like Python, TCL (the scripting language used for Expect) doesn't have constants.
I would suggest going the python route. Define them in all caps, don't change them and hope everyone else gets the hint.
set COPYPATH "/home/bob/tmp"
set PI 3.14159265359
If you really think you need them, there are some hacks in the link glenn jackman posted in the comments https://wiki.tcl-lang.org/page/constants.

What does VAR_NAME=${VAR_NAME:-"/some/path/file"} mean

What does VAR_NAME=${VAR_NAME:-"/some/path/file"} mean in an shell script?
This is for an init script, I'm writing a custom one to get some of our startup operations into init scripts so that we can start them automatically on boot, but I don't have much experience with shell scripting so I'm using a startup script for an unrelated piece of software that's we've customized in the past.
The path pointed to is to a file that contains configuration values that override defaults set in the script.
I'm having trouble figuring out what that construct really means (the :- part in particular).
The script I'm working off of also seems to chain this operation together to resolve which value to use such as:
LOG_FILE=${LOG_FILE:-${LOGFILE:-$DEFAULT_LOG_FILE}}
${parameter:-word}
Use Default Values. If parameter is unset or null, the expansion
of word shall be substituted; otherwise, the value of parameter shall be
substituted.
It sets VAR_NAME equal to VAR_NAME if it exists or /some/path/file if it doesn't.
Chaining it would only make sense if the variable names were different going down the chain.

Documenting bash functions

I would like to add documentation for bash functions so that users can lookup the functions with man. There should be no visible difference between my functions and actual commands.
I know I can do this by overriding man with a function that checks for my own functions. Is there another way?
If you have your man pages created (which is a task in itself) then what you can do is put them somewhere on the system like /usr/local/man (or wherever you like, really), then edit the system-wide $MANPATH variable to include that location. Then the man pages will be available.
Real shell functions are not documented by individual man pages but by the help builtin command. You would have to override that. But even I would not look there for information.
Just generate normal man pages and throw them into /usr/local/man/manX or /usr/local/share/man/manX - whatever your distribution already provides. Check /etc/manpath.config that this directory is already mentioned there. That way no one must fiddle in their startup files with the MANPATH environment variable.
Each manpage should also contain a clearly visible section explaining, that this is a function and not a command and what the difference is.
After that the social part kicks in: Tell everyone at every occasion about that documetation. By every I mean every, not only suitable. :-)

Does Cygwin (or an actual UNIX shell) have some command to import names from another namespace to the current namespace, as in Python?

In Python, we can use "import" to import the names of another namespace into the current namespace.
Similarly, is there a notion like "namespace" in existence in UNIX shell scripting at all? If so, then does Cygwin (or an actual UNIX shell) have some command to import names from another namespace to the current namespace, as in Python? Thanks.
Note to the community members with admin priviledges: I really think this question IS a programming question instead of a "superuser" question. Please kindly elaborate on why if you disagree with that. Thanks a lot for your time.
There is no way to do exactly what you are asking for.
The source envFile command and it's alternate . envFile can be very helpful.
envFile file will just be a list of environment assingments.
FrontOfficeSystem=MyFrontOffice
BackOfficeSystem=myBackOffice
When you include the command in your script to 'source' the envFile (any name will work), the shell reads the code as if it was directly in your main shell script. Like 'include' in a lot of langauges. But namespaces, ... nope. See next.
More helpful : see indirect references in advanced Bash scripting, this is probably better than using eval ... (per below), but I haven't had the opportunity to work with it.
finally, you may also benefit from eval and varname indirection, i.e.
src=FrontOffice
eval \$${src}System="${src} has data"
src=BackOffice
eval \$${src}System="${src} has data"
Not a great example, but I don't have access to the scripts where I really went to town on this idea. It helped me genericize (sp) some code that otherwise would have had to be repeated 10 times, for each data src (I put the repeating block of code in a for loop, with the src names as the element list for the for(each), then the eval would expand ${src}System as FrontOfficeSystem, BackOfficeSystem). If you windup with spaces in your values for your src list, then all bets are off.
use set -vx in your terminal window and copy/paste above code to see how it works. It might help.
I hope this helps.
P.S. as you appear to be a new user, if you get an answer that helps you please remember to mark it as accepted, and/or give it a + (or -) as a useful answer.

Resources