1

Given the variables listed below:

echo ${userupper}_PYTHON
# YTU_PYTHON
echo $YTU_PYTHON
# /home/ytu/anaconda3/bin/python
echo $path
# foo.py

Now I'd like to execute /home/ytu/anaconda3/bin/python foo.py with userupper and path. I tried $(${userupper}_PYTHON) $path but it ends up with error messages including:

YTU_PYTHON: not found
foo.py: not found

It seems like it takes $(${userupper}_PYTHON) as bare YTU_PYTHON rather than expected $YTU_PYTHON. How should I do to make it right?


Edits:

The suggested duplication should have solved my problem. However for some unknown reasons it's not working.

#!/usr/bin/env bash

for user in ytu
do
  . /home/${user}/.profile
  userupper=$(echo ${user} | awk '{print toupper($0)}')
  userpython=${userupper}_PYTHON
  cd /home/${user}/H2-ML/crons
  for path in $(ls | grep ^${user}_.*_monthly_report.py$)
  do
    echo ${userpython}
    echo $path
    echo $YTU_PYTHON
    echo ${!userpython}
  done
done

The code chunk above returns:

YTU_PYTHON
ytu_clinic249_monthly_report.py
/home/ytu/anaconda3/bin/python
send_monthly_reports.sh: 14: send_monthly_reports.sh: Bad substitution

, which makes me so confused.

ytu
  • 1,822
  • 3
  • 19
  • 42
  • Possible duplicate of [How to use a variable's value as another variable's name in bash](https://stackoverflow.com/questions/9714902/how-to-use-a-variables-value-as-another-variables-name-in-bash) – Biffen Nov 02 '18 at 11:01
  • @Biffen I really appreciate your suggestion and that indeed should have solved my problem. However somehow it's not. Please consider looking at my edits and giving me some feedbacks. Thank you. – ytu Nov 02 '18 at 16:00
  • [BashFAQ #50](http://mywiki.wooledge.org/BashFAQ/050) -- *I'm trying to put a command in a variable, but the complex cases always fail!* -- will be eventually relevant (once you've fixed other issues). – Charles Duffy Nov 02 '18 at 21:10
  • Also see the various quoting bugs identified by http://shellcheck.net/. And don't trust `echo` to tell you the truth -- if you want robust logging, use `bash -x` / `set -x`. – Charles Duffy Nov 02 '18 at 21:12

1 Answers1

0

Try this:

command=${userupper}_PYTHON
echo ${!command} $path # ommit echo if you want to execute command

in your case it echos:

/home/ytu/anaconda3/bin/python foo.py

Here is link that might be useful if you want to write bash scripts. You should not parse ls output in the nutshell.

You also create unnecessary new process, both lines do the same:

$(echo ${user} | awk '{print toupper($0)}')
${user^^} #paramenter expansion
prenc
  • 151
  • 2
  • 13
  • That should have worked, but it is not. Please see my edits above. Thank you for the help! – ytu Nov 02 '18 at 15:52
  • @ytu is that whole script what you pasted, because I don't see first line with interpreter #!/bin/bash for example – prenc Nov 02 '18 at 18:22
  • I use `#!/usr/bin/env bash`. Other than that it's the whole script. If I shouldn't parse `ls` output then how do I loop through the files? Besides the error is not caused by parsing `ls`. BTW `${user^^}` works only on Ubuntu but not on MacOS. – ytu Nov 02 '18 at 21:02
  • "How do I loop through the files?" -- with a shell wildcard. `for path in "$user"_*_monthly_report.py; do`. See [ParsingLs](http://mywiki.wooledge.org/ParsingLs). – Charles Duffy Nov 02 '18 at 21:09
  • @ytu, ...btw, `${user^^}` works perfectly fine on MacOS if you install a modern bash (something you can do with Nix, MacPorts or Homebrew). – Charles Duffy Nov 02 '18 at 21:30
  • @CharlesDuffy in fact ${user^^} gives me "Bad substitution" on Ubuntu in a shell script... (but it works in interactive terminal). – ytu Nov 03 '18 at 11:24
  • BTW I thought it should be better to _not_ to assume what user's bash is when developing, no? – ytu Nov 03 '18 at 11:26
  • 1
    @ytu, that would be the case if you used a `#!/bin/sh` script (or ran `sh myscript`, explicitly asking to run it with a POSIX sh interpreter), but that's *not a bash script*. Use `#!/usr/bin/env bash` for bash. – Charles Duffy Nov 03 '18 at 12:46
  • @ytu, and correct, it's better not to assume. I prefix my scripts with something like `case $BASH_VERSION in ''|[123].*) echo "ERROR: Bash 4.0 or newer required" >&2; exit 1;; esac` -- that way you're not *assuming*, but *ensuring*. Bash 4.0 is came out in 2009 -- there's no excuse for running anything prior today. (Apple ships 3.2, a series from 2006, because they aren't willing to agree with the license for modern versions -- but if they don't change that policy, their release will just get more and more out-of-date in perpetuity). – Charles Duffy Nov 03 '18 at 12:47