The way it's supposed work is that, at the point when you get a shell prompt, both .profile
and .bashrc
have been run. The specific details of how you get to that point are of secondary relevance, but if either of the files didn't get run at all, you'd have a shell with incomplete settings.
The reason terminal emulators on Linux (and other X-based systems) don't need to run .profile
themselves is that it will normally have been run already when you logged in to X. The settings in .profile
are supposed to be of the kind that can be inherited by subprocesses, so as long as it's executed once when you log in (e.g. via .Xsession
), any further subshells don't need to re-run it.
As the Debian wiki page linked by Alan Shutko explains:
"Why is .bashrc
a separate file from .bash_profile
, then? This is done for mostly historical reasons, when machines were extremely slow compared to today's workstations. Processing the commands in .profile
or .bash_profile
could take quite a long time, especially on a machine where a lot of the work had to be done by external commands (pre-bash). So the difficult initial set-up commands, which create environment variables that can be passed down to child processes, are put in .bash_profile
. The transient settings and aliases which are not inherited are put in .bashrc
so that they can be re-read by every subshell."
All the same rules hold on OSX, too, except for one thing — the OSX GUI doesn't run .profile
when you log in, apparently because it has its own method of loading global settings. But that means that a terminal emulator on OSX does need to run .profile
(by telling the shell it launches that it's a login shell), otherwise you'd end up with a potentially crippled shell.
Now, a kind of a silly peculiarity of bash, not shared by most other shells, is that it will not automatically run .bashrc
if it's started as a login shell. The standard work-around for that is to include something like the following commands in .bash_profile
:
[[ -e ~/.profile ]] && source ~/.profile # load generic profile settings
[[ -e ~/.bashrc ]] && source ~/.bashrc # load aliases etc.
Alternatively, it's possible to have no .bash_profile
at all, and just include some bash-specific code in the generic .profile
file to run .bashrc
if needed.
If the OSX default .bash_profile
or .profile
doesn't do this, then that's arguably a bug. In any case, the proper work-around is to simply add those lines to .bash_profile
.
Edit: As strugee notes, the default shell on OSX used to be tcsh, whose behavior is much saner in this respect: when run as an interactive login shell, tcsh automatically reads both .profile
and .tcshrc
/ .cshrc
, and thus does not need any workarounds like the .bash_profile
trick shown above.
Based on this, I'm 99% sure that the failure of OSX to supply an appropriate default .bash_profile
is because, when they switched from tcsh to bash, the folks at Apple simply didn't notice this little wart in bash's startup behavior. With tcsh, no such tricks were needed — starting tcsh as a login shell from an OSX terminal emulator Just Plain Works and does the right thing without such kluges.
The commands within each group run in parallel, and the groups run sequentially, each group of parallel commands waiting for the previous group to finish before starting execution.
The following is a working example:
Assume 3 groups of commands as in the code below. In each group the three commands are started in the background with &
.
The 3 commands will be started almost at the same time and run in parallel while the script waits
for them to finish.
After all three commands in the the third group exit, command 10
will execute.
$ cat command_groups.sh
#!/bin/sh
command() {
echo $1 start
sleep $(( $1 & 03 )) # keep the seconds value within 0-3
echo $1 complete
}
echo First Group:
command 1 &
command 2 &
command 3 &
wait
echo Second Group:
command 4 &
command 5 &
command 6 &
wait
echo Third Group:
command 7 &
command 8 &
command 9 &
wait
echo Not really a group, no need for background/wait:
command 10
$ sh command_groups.sh
First Group:
1 start
2 start
3 start
1 complete
2 complete
3 complete
Second Group:
4 start
5 start
6 start
4 complete
5 complete
6 complete
Third Group:
7 start
8 start
9 start
8 complete
9 complete
7 complete
Not really a group, no need for background/wait:
10 start
10 complete
$
Best Answer
You can use a for loop:
If you have multiple parameters, and you want all the various permutations of all parameters, as @Fox noted in a comment below, you can use nested loops. Suppose, for example, you had a
--name
parameter whose values could ben1
,n2
, andn3
, then you could do:You could put that in a file, for example
runExperiment.sh
and include this as the first line:#!/bin/bash
. You could then run the script using either:Or, you could make the script executable, then run it:
If you're interested in some results before others, that'll guide how you structure the loops. In my example above, the script will run:
So it runs all experiments for iteration 10 before moving on to the next iteration. If instead you wanted all experiments for name
n1
before moving on to the next, you could make the name loop the "outer" loop.