Jpp
ulib.sh
Go to the documentation of this file.
1 #!/bin/zsh
2 #
3 #
4 # \author mdejong
5 #
6 #--------------------------------------------------------------------------------------
7 #
8 # Utility script for zsh library functions.
9 #
10 #--------------------------------------------------------------------------------------
11 
12 version=1.0
13 
14 if [[ "$DEBUG" == "" ]]; then
15 typeset -i DEBUG=0 # debug level
16 export DEBUG
17 fi
18 
19 typeset -i TIMER=0 # timer
20 export TIMER
21 
22 export DEFAULT_OPTION=- # default option
23 
24 
25 # Wild card for any valid run number to be used as ${~ANY_RUN_NUMBER}.
26 
27 export ANY_RUN_NUMBER="[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]"
28 
29 export PI=3.14159265359
30 
31 export BLUE="\e[94m"
32 export GREEN="\e[92m"
33 export RED="\e[91m"
34 export RESET="\e[0m"
35 export BOLD="\e[1m"
36 
37 export TIMESTAMP=\#splitline{}{\#splitline{%d:%m:%y}{\ \ %H:%M}}%F1970-01-01\ 00:00:00
38 
39 
40 #
41 # debug messages
42 #
43 function fatal() {
44  echo -e $RED`date` FATAL $* $RESET
45  exit 1
46 }
47 function error() { if (( $DEBUG >= 0 )); then echo -e $RED`date` ERROR $* $RESET; fi }
48 function notice() { if (( $DEBUG >= 1 )); then echo -e `date` NOTICE $* ; fi }
49 function status() { if (( $DEBUG >= 2 )); then echo -e `date` STATUS $* ; fi }
50 function warning() { if (( $DEBUG >= 2 )); then echo -e `date` WARNING $* ; fi }
51 function debug() { if (( $DEBUG >= 3 )); then echo -e `date` DEBUG $* ; fi }
52 
53 
54 #
55 # Method to check for usage of script.
56 #
57 # \param 1-N list of command line options
58 # \return 0 for option -h; else 1
59 #
60 function do_usage()
61 {
62  for variable in $*; do
63  if [[ "$variable" == "-h" || "$variable" == "-h!" ]]; then
64  return 0
65  fi
66  done
67 
68  return 1
69 }
70 
71 
72 #
73 # Method to print usage of script and exit.
74 #
75 # \param 1-N usage
76 #
77 function usage()
78 {
79  echo "$*"
80  exit
81 }
82 
83 
84 #
85 # Method to print environment variables.
86 #
87 function print_env()
88 {
89  env
90 }
91 
92 
93 #
94 # check exit code
95 # The last parameter refers to the exit code.
96 #
97 # \param 1-N message
98 # \param N exit code
99 #
100 function check_exit_code()
101 {
102  if (( $argv[-1] )); then
103  error $*
104  exit $argv[-1]
105  else
106  notice $*
107  fi
108 }
109 
110 
111 #
112 # test quality
113 #
114 # \param 1 first value
115 # \param 2 second value
116 #
117 function test_equality
118 {
119  if [[ "$1" != "$2" ]]; then
120  fatal "<$1> != <$2>"
121  else
122  debug "<$1> == <$2>"
123  fi
124 }
125 
126 
127 #
128 # check exit code alias
129 #
130 alias CHECK_EXIT_CODE="check_exit_code \$0 \$* \$?"
131 
132 
133 #
134 # Method to check if inside a conda env.
135 #
136 function has_conda()
137 {
138  if [ -n "${CONDA_PREFIX+1}" ]; then
139  return 0
140  else
141  return 1
142  fi
143 }
144 
145 
146 #
147 # Method to check for CC Lyon.
148 #
149 # \return 1 for CC Lyon; else 0
150 #
151 function is_CCLyon()
152 {
153  LOCALHOST=`hostname`
154 
155  if [[ -n "${LOCALHOST}" && "${LOCALHOST:0:2}" = "cc" ]]; then
156  return 0
157  else
158  return 1
159  fi
160 }
161 
162 
163 #
164 # Method to get file name of source code.
165 #
166 # \param 1 executable file
167 # \return source file
168 #
169 function get_source()
170 {
171  file=`which $1 2> /dev/null`
172 
173  if [[ -n "${file}" && -x ${file} ]]; then
174  if [[ $file = *.sh || $file = *.csh ]]; then
175  source=${file}
176  else
177  source=`${file} -v 2> /dev/null | sed -n 's/source: *//p'`
178  fi
179  else
180  source=$1
181  fi
182 
183  echo $source
184 }
185 
186 
187 #
188 # Method to define variable.
189 #
190 # \param 1 variable
191 #
192 function define_variable()
193 {
194  local variable=$1
195 
196  eval export $variable
197 }
198 
199 
200 #
201 # Method to set variable.
202 # Note that a value equal to $DEFAULT_OPTION will not modify the variable.
203 #
204 # \param 1 variable
205 # \param 2-N value(s)
206 #
207 function set_variable()
208 {
209  local variable=$1
210  shift
211 
212  if [[ "$*" != "$DEFAULT_OPTION" ]]; then
213  eval export $variable=\"$\*\"
214  fi
215 }
216 
217 
218 #
219 # Method to unset variable.
220 #
221 # \param 1 variable
222 #
223 function unset_variable()
224 {
225  local variable=$1
226 
227  eval unset $variable
228 }
229 
230 
231 #
232 # Method to print variables.
233 #
234 # \param 1-N list of variables
235 #
236 function print_variable()
237 {
238  for variable in $*; do
239  eval value=\${$variable}
240  printf "%-20s = %s\n" ${variable} "${value}"
241  done
242 }
243 
244 
245 #
246 # Method to check validity of variables.
247 #
248 # \param 1-N list of variables
249 #
250 function check_variable()
251 {
252  for variable in $*; do
253  eval value=$+${variable}
254  if (( ${value} == 0 )); then
255  fatal "Variable ${variable} not defined."
256  fi
257  done
258 }
259 
260 
261 #
262 # Method to set array.
263 #
264 # \param 1 array name
265 # \param 2-N values
266 #
267 function set_array()
268 {
269  local variable=$1
270  shift
271 
272  eval $variable=\($\*\)
273 }
274 
275 
276 #
277 # Method to count directory in ':' separated path list.
278 #
279 # \param 1 path list
280 # \param 2 directory
281 #
282 function count_directory()
283 {
284  eval key=\${$1}
285 
286  echo -n $key | tr ":" "\n" | grep "^\\${2}$" | wc -w
287 }
288 
289 
290 #
291 # Method to remove directory from ':' separated path list.
292 #
293 # \param 1 path list
294 # \param 2 directory
295 #
296 function remove_directory()
297 {
298  eval key=\${$1}
299  eval value=$2
300 
301  if [[ -n "$key" && -n "$value" ]]; then
302  export $1=`eval echo $key | tr ":" "\n" | grep -v "^\\\\${value}$" | tr "\n" ":" | sed 's/:\$//'`
303  fi
304 }
305 
306 
307 #
308 # Method to remove variable from ':' separated path list.
309 #
310 # \param 1 path list
311 # \param 2 variable
312 #
313 function remove_variable()
314 {
315  eval key=\${$1}
316  eval value=\${$2}
317 
318  if [[ -n "$key" && -n "$value" ]]; then
319  remove_directory $1 $value
320  fi
321 }
322 
323 
324 #
325 # Method to insert directory into ':' separated path list.
326 #
327 # \param 1 path list
328 # \param 2 directory
329 #
330 function insert_directory()
331 {
332  eval key=\${$1}
333 
334  if [[ -z "$key" ]]; then
335  export $1=$2
336  elif (( `eval echo -n $key | tr ":" "\n" | grep "^\\\\${2}$" | wc -w` == 0 )); then
337  export $1=$2:${key}
338  fi
339 }
340 
341 
342 #
343 # Method to check process path.
344 #
345 # \param 1-N list of process names
346 #
347 function check_process()
348 {
349  for process in $*; do
350 
351  local bin=`which $process 2>& /dev/null`
352  debug "Check process ${process}=${bin}"
353 
354  if [ -z "${bin}" ]; then
355  fatal "Process ${process} not found."
356  fi
357  done
358 }
359 
360 
361 #
362 # Method to check file access.
363 #
364 # \param 1-N list of files
365 #
366 function check_input_file()
367 {
368  if (( $# == 0 )); then
369  fatal "No input file."
370  fi
371 
372  for file in `echo $*`; do
373 
374  debug "Check input file: ${file}"
375 
376  if [[ ! -f ${file} ]]; then
377  fatal "File ${file} not found."
378  elif [[ ! -r ${file} ]]; then
379  fatal "File ${file} not readable."
380  fi
381  done
382 }
383 
384 
385 #
386 # Method to check file access.
387 #
388 # \param 1-N list of files
389 #
390 function check_output_file()
391 {
392  for file in `echo $*`; do
393 
394  debug "Check output file: ${file}"
395 
396  if [[ -f ${file} ]]; then
397  fatal "File ${file} already exists."
398  fi
399  done
400 }
401 
402 
403 #
404 # Method to reuse file.
405 # Note that this method may require user interaction.
406 #
407 # \param 1 file name
408 # \return 1 when absent; else 0
409 #
410 function reuse_file()
411 {
412  if [[ -f $1 ]]; then
413  rm -i $1
414  fi
415 
416  if [[ ! -f $1 ]]; then
417  return 1
418  else
419  return 0
420  fi
421 }
422 
423 
424 #
425 # Get host IP address
426 #
427 function get_ip_address()
428 {
429  hostname --all-ip-addresses | cut --delimiter=' ' -f1
430 }
431 
432 
433 #
434 # Get process identifier.
435 #
436 # \param [hostname]
437 # \param process name
438 # \return PID
439 #
440 function get_pid()
441 {
442  if (( $# == 1 )); then
443  exec ps h -o "%p" -C $1
444  elif (( $# == 2 )); then
445  exec ssh $1 "ps h -o "%p" -C $2"
446  fi
447 }
448 
449 
450 #
451 # Method to get least significant digit.
452 #
453 # \param value
454 # \return value
455 #
456 function getLSD()
457 {
458  printf "%f\n" `echo $1 | sed -n "s/[+-]\?\([0-9]*.\?[0-9]*\)[1-9]\([0]*.\?\)/\1A\2/p" | sed 's/[1-9]/0/g' | sed 's/A/1/'`
459 }
460 
461 
462 #
463 # Method to start timer
464 #
465 function timer_start()
466 {
467  TIMER=$(date +%s)
468 }
469 
470 
471 #
472 # Method to stop timer
473 #
474 function timer_stop()
475 {
476  TIMER=$(($(date +%s) - $TIMER))
477 }
478 
479 
480 #
481 # Method to print timer
482 #
483 function timer_print()
484 {
485  echo "Elapsed time $TIMER s."
486 }
487 
488 
489 #
490 # Make communication with process.
491 #
492 # Note that:
493 # - FD_O is the actual file descriptor for writing to actual process and
494 # - FD_I is the actual file descriptor for reading from process.
495 #
496 # \param 1 process name
497 # \param 2-N optional argument(s)
498 #
499 function attach()
500 {
501  PROCESS=$1 # process
502 
503  shift
504 
505  ARGS="$*" # optional arguments
506 
507  FIFO_O=/tmp/${PROCESS}_writing # named pipe for writing
508  FIFO_I=/tmp/${PROCESS}_reading # named pipe for reading
509 
510  rm -f $FIFO_O
511  rm -f $FIFO_I
512 
513  mkfifo $FIFO_O # create a new FIFO
514  mkfifo $FIFO_I # create a new FIFO
515 
516  eval "exec {FD_O}<>$FIFO_O" # attach file descriptor to FIFO
517  eval "exec {FD_I}<>$FIFO_I" # attach file descriptor to FIFO
518 
519  # launch process in background and cleanup afterwards
520 
521  eval \($PROCESS \
522  $ARGS \
523  < $FIFO_O \
524  > $FIFO_I \&\& \
525  rm -f $FIFO_O \&\& \
526  rm -f $FIFO_I\) \&
527 }
528 
529 
530 #
531 # Remove communication with process.
532 #
533 # \param 1 file descriptor for writing to process
534 #
535 function detach()
536 {
537  if (( $# == 0 )); then
538  FD=$FD_O
539  else
540  FD=$1
541  fi
542 
543  print -u $FD "^D"
544 }