10seconds_install: Update copyright year.
[parallel.git] / src / env_parallel.pdksh
blob33077f7998961449b0471fe686c9db2f70a4be55
1 #!/usr/bin/env pdksh
3 # This file must be sourced in pdksh:
5 #   source `which env_parallel.pdksh`
7 # after which 'env_parallel' works
10 # Copyright (C) 2016-2019
11 # Ole Tange and Free Software Foundation, Inc.
13 # This program is free software; you can redistribute it and/or modify
14 # it under the terms of the GNU General Public License as published by
15 # the Free Software Foundation; either version 3 of the License, or
16 # (at your option) any later version.
18 # This program is distributed in the hope that it will be useful, but
19 # WITHOUT ANY WARRANTY; without even the implied warranty of
20 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
21 # General Public License for more details.
23 # You should have received a copy of the GNU General Public License
24 # along with this program; if not, see <http://www.gnu.org/licenses/>
25 # or write to the Free Software Foundation, Inc., 51 Franklin St,
26 # Fifth Floor, Boston, MA 02110-1301 USA
28 env_parallel() {
29     # env_parallel.pdksh
31     _names_of_ALIASES() {
32         compgen -a
33     }
34     _bodies_of_ALIASES() {
35         alias "$@" | perl -pe 's/^/alias /'
36     }
37     _names_of_FUNCTIONS() {
38         compgen -A function
39     }
40     _bodies_of_FUNCTIONS() {
41         typeset -f "$@"
42     }
43     _names_of_VARIABLES() {
44         compgen -A variable
45     }
46     _bodies_of_VARIABLES() {
47         typeset -p "$@"
48     }
49     _remove_bad_NAMES() {
50         _tmp_READONLY="$(mktemp)"
51         readonly > "$_tmp_READONLY"
52         # Do not transfer vars and funcs from env_parallel
53         grep -Ev '^(_names_of_ALIASES|_bodies_of_ALIASES|_names_of_maybe_FUNCTIONS|_names_of_FUNCTIONS|_bodies_of_FUNCTIONS|_names_of_VARIABLES|_bodies_of_VARIABLES|_remove_bad_NAMES|_prefix_PARALLEL_ENV|_get_ignored_VARS|_make_grep_REGEXP|_ignore_UNDERSCORE|_alias_NAMES|_list_alias_BODIES|_function_NAMES|_list_function_BODIES|_variable_NAMES|_list_variable_VALUES|_prefix_PARALLEL_ENV|PARALLEL_ENV|PARALLEL_TMP)$' |
54             # Filter names matching --env
55             grep -E "^$_grep_REGEXP"\$ | grep -vE "^$_ignore_UNDERSCORE"\$ |
56             grep -vFf $_tmp_READONLY |
57             grep -Ev '^(PIPESTATUS)'
58         rm $_tmp_READONLY
59         unset _tmp_READONLY
60     }
61     _prefix_PARALLEL_ENV() {
62         shopt 2>/dev/null |
63         perl -pe 's:\s+off:;: and s/^/shopt -u /;
64                   s:\s+on:;: and s/^/shopt -s /;
65                   s:;$:&>/dev/null;:';
66         echo 'shopt -s expand_aliases &>/dev/null';
67     }
69     _get_ignored_VARS() {
70         perl -e '
71             for(@ARGV){
72                 $next_is_env and push @envvar, split/,/, $_;
73                 $next_is_env=/^--env$/;
74             }
75             if(grep { /^_$/ } @envvar) {
76                 if(not open(IN, "<", "$ENV{HOME}/.parallel/ignored_vars")) {
77                     print STDERR "parallel: Error: ",
78                     "Run \"parallel --record-env\" in a clean environment first.\n";
79                 } else {
80                     chomp(@ignored_vars = <IN>);
81                     $vars = join "|",map { quotemeta $_ } @ignored_vars;
82                     print $vars ? "($vars)" : "(,,nO,,VaRs,,)";
83                 }
84             }
85             ' -- "$@"
86     }
88     # Get the --env variables if set
89     # --env _ should be ignored
90     # and convert  a b c  to (a|b|c)
91     # If --env not set: Match everything (.*)
92     _make_grep_REGEXP() {
93         perl -e '
94             for(@ARGV){
95                 /^_$/ and $next_is_env = 0;
96                 $next_is_env and push @envvar, split/,/, $_;
97                 $next_is_env = /^--env$/;
98             }
99             $vars = join "|",map { quotemeta $_ } @envvar;
100             print $vars ? "($vars)" : "(.*)";
101             ' -- "$@"
102     }
104     if which parallel | grep 'no parallel in' >/dev/null; then
105         echo 'env_parallel: Error: parallel must be in $PATH.' >&2
106         return 1
107     fi
108     if which parallel >/dev/null; then
109         true which on linux
110     else
111         echo 'env_parallel: Error: parallel must be in $PATH.' >&2
112         return 1
113     fi
115     # Grep regexp for vars given by --env
116     _grep_REGEXP="`_make_grep_REGEXP \"$@\"`"
118     # Deal with --env _
119     _ignore_UNDERSCORE="`_get_ignored_VARS \"$@\"`"
121     # Get the --env variables if set
122     # --env _ should be ignored
123     # and convert  a b c  to (a|b|c)
124     # If --env not set: Match everything (.*)
125     _grep_REGEXP="$(
126         perl -e '
127             for(@ARGV){
128                 /^_$/ and $next_is_env = 0;
129                 $next_is_env and push @envvar, split/,/, $_;
130                 $next_is_env = /^--env$/;
131             }
132             $vars = join "|",map { quotemeta $_ } @envvar;
133             print $vars ? "($vars)" : "(.*)";
134             ' -- "$@"
135     )"
136     # Deal with --env _
137     _ignore_UNDERSCORE="$(
138         perl -e '
139             for(@ARGV){
140                 $next_is_env and push @envvar, split/,/, $_;
141                 $next_is_env=/^--env$/;
142             }
143             if(grep { /^_$/ } @envvar) {
144                 if(not open(IN, "<", "$ENV{HOME}/.parallel/ignored_vars")) {
145                     print STDERR "parallel: Error: ",
146                     "Run \"parallel --record-env\" in a clean environment first.\n";
147                 } else {
148                     chomp(@ignored_vars = <IN>);
149                     $vars = join "|",map { quotemeta $_ } "env_parallel", @ignored_vars;
150                     print $vars ? "($vars)" : "(,,nO,,VaRs,,)";
151                 }
152             }
153             ' -- "$@"
154     )"
156     # --record-env
157     if perl -e 'exit grep { /^--record-env$/ } @ARGV' -- "$@"; then
158         true skip
159     else
160         (_names_of_ALIASES;
161          _names_of_FUNCTIONS;
162          _names_of_VARIABLES) |
163             cat > $HOME/.parallel/ignored_vars
164         return 0
165     fi
166     
167     # Grep alias names
168     _alias_NAMES="`_names_of_ALIASES | _remove_bad_NAMES`"
169     _list_alias_BODIES="_bodies_of_ALIASES $_alias_NAMES"
170     if [ "$_alias_NAMES" = "" ] ; then
171         # no aliases selected
172         _list_alias_BODIES="true"
173     fi
174     unset _alias_NAMES
176     # Grep function names
177     _function_NAMES="`_names_of_FUNCTIONS | _remove_bad_NAMES`"
178     _list_function_BODIES="_bodies_of_FUNCTIONS $_function_NAMES"
179     if [ "$_function_NAMES" = "" ] ; then
180         # no functions selected
181         _list_function_BODIES="true"
182     fi
183     unset _function_NAMES
185     # Grep variable names
186     _variable_NAMES="`_names_of_VARIABLES | _remove_bad_NAMES`"
187     _list_variable_VALUES="_bodies_of_VARIABLES $_variable_NAMES"
188     if [ "$_variable_NAMES" = "" ] ; then
189         # no variables selected
190         _list_variable_VALUES="true"
191     fi
192     unset _variable_NAMES
194     # eval is needed for aliases - cannot explain why
195     export PARALLEL_ENV="`
196         eval $_list_alias_BODIES;
197         $_list_function_BODIES
198         $_list_variable_VALUES;
199     `";
200     unset _list_alias_BODIES
201     unset _list_variable_VALUES
202     unset _list_function_BODIES
203     `which parallel` "$@";
204     _parallel_exit_CODE=$?
205     unset PARALLEL_ENV;
206     return $_parallel_exit_CODE