1

In the example script below it is used to send to one or two email addresses, depending on which process is using the script. Do I need to add $3 to account for an additional email address or is $2 sufficient?

(
for file in /usr/app/tst/$1/MS_CASE_ST*.csv;
do
   uuencode ${file} $(basename ${file})
done
) | mailx -s "MS_CASE_ST*.csv file contains data. Please Research" $2 

An example of how the script, example.sh, is executed:

$ ./example.sh output [email protected] [email protected]
Jeff Schaller
  • 66,199
  • 35
  • 114
  • 250
Emile
  • 385
  • 1
  • 5
  • 13
  • We're in the 21st Century. Why are you using `uuencode`? – roaima Jul 12 '17 at 17:16
  • ...because I'm new and if it's not broken... Unless you would like to teach me? – Emile Jul 12 '17 at 18:17
  • Certainly. It belongs as its own question really, though. Feel free to reference this question as background to your new one. If you let us know here where the new question is I'm sure I'll not be the only one able to make suggestions about a MIME-compliant alternative. – roaima Jul 12 '17 at 19:30
  • 1
    @roaima https://unix.stackexchange.com/questions/378066/what-are-some-better-options-than-uuencode-in-bash – Emile Jul 12 '17 at 20:36
  • Of course you should use double quotes: `uuencode "$file" "$(basename "$file")"` (and `"$2"` or `"${@:2}"`). [*`${variable_name}`* doesn’t mean what you think it does …](https://unix.stackexchange.com/q/32210/23408#286525), and maybe see also [Bash quotes unescaped on command substitution](https://superuser.com/q/909764/150988). – Scott - Слава Україні Jul 12 '17 at 22:41

3 Answers3

7

$2 will always be only the second argument. $@ is an array of all the arguments, so if you want the second until the end you could do:

... | mailx -s "MS_CASE_ST*.csv file contains data.  Please research" "${@:2}"

the :2 is specifying an offset in the parameter expansion when expanding the $@ array

Eric Renouf
  • 18,141
  • 4
  • 49
  • 65
  • 1
    **Warning:** This (using `:2`) will only work if `bash` is used to run the script. I appreciate that is usually will, but if the script has a shebang for `/bin/sh`, and `sh` has not been aliased to `bash`, it won't work. An alternative would be to use: output=$1; shift and then just use `$@`. – Bob Eager Jul 12 '17 at 17:17
  • @BobEager I took from the `bash` tag that it was probably a reasonable assumption, but it's good to call that out – Eric Renouf Jul 12 '17 at 17:18
  • The script has #!/bin/bash, does the shell running the script also have to be in bash? I'm pretty new but I feel like I said this right... in either case, sorry about that. – Emile Jul 12 '17 at 18:13
  • @Emile If you run it as `path/to/script` it will use the shebang line, as you described it would use `bash` regardless of the current shell. If you use `sh script` it will use `sh` regardless of what the shebang line says. If you use `source script` it will use your current shell regardless of what the shebang line says, so it all depends on how you run it – Eric Renouf Jul 12 '17 at 18:16
  • Thanks for the info... Using the autosys application we use the the `/path/to/script` format for the command. However, all the previous created scripts are named _script.sh_ and within each script designates which shell. – Emile Jul 12 '17 at 18:23
  • *nix in general doesn't care about extensions, so you can have `.sh` if you like, or ignore it if you don't want it, no harm either way – Eric Renouf Jul 12 '17 at 18:24
1

To support multiple recipients with this particular script, use $1 as the path element, then shift this off from the list of positional parameters. Now the list, $@, contains only recipients.

#!/bin/bash

dir=$1
shift

shopt -s nullglob

for file in "/usr/app/tst/$dir/MS_CASE_ST"*.csv; do
    uuencode "$file" "$( basename "$file" )"  # or uuencode "$file" "${file##*/}"
done | mailx -s 'MS_CASE_ST*.csv file(s) contains data. Please Research' "$@"

A few notes:

  • Be careful and double quote any variable expansions, or you will have issues when a pathname contains spaces or filename globbing characters etc. (and single quote static strings).

  • Quoting $@ as "$@" ensures that it expands to individually quoted elements.

  • By setting the nullglob shell option in bash, we ensure that the globbing pattern that the loop uses expands to nothing if it does not match any existing pathname.

Kusalananda
  • 320,670
  • 36
  • 633
  • 936
0

This question seems to be confusing shell arguments with the read command. They're different:

  1. The shell:

    set -- foo bar baz buzz zap bang ; echo $2
    

    Output is only the second word:

    bar
    
  2. The read command with two variable names:

    echo foo bar baz buzz zap bang | (read x y ; echo $y )
    

    Outputs everything including and past the 2nd word:

    bar baz buzz zap bang
    
agc
  • 7,045
  • 3
  • 23
  • 53
  • I don't think it's confusing those things, it's looking at using the first argument as the directory to process and the rest as the recipient email addresses, then the output of the left side of the pipe will be the body of the mail message – Eric Renouf Jul 12 '17 at 22:37
  • @EricRenouf: I found agc’s “answer” a little confusing at first — and, in fact, I believe that this post is ***not an answer*** — but I believe that agc’s point is that the OP seemed to think that positional parameters worked like `read` arguments, as in “I only ever mentioned `$1` and `$2`, so I expect ``$1`` to be the first token and ``$2`` to refer to everything else.” Of course, if it worked that way, then that wouldn’t work either, because `$2` would be a single string, with all the email addresses concatenated. – G-Man Says 'Reinstate Monica' Jul 12 '17 at 22:49
  • @G-Man ah, I see that interpretation now. Thanks – Eric Renouf Jul 12 '17 at 22:54
  • 1
    @G-Man, Re "*if it worked that way*": since `$2` is unquoted, the shell would not protect any whitespace, so if we imagine that `mailx -s "MS_CASE_ST*.csv file contains data. Please Research" $2` used a `read`-like parse syntax then `mailx` would see as many arguments as `$2` contained whitespace separated words. (**If** it worked that way, which of course it does not...) – agc Jul 13 '17 at 05:05
  • @agc: Yeah, I was waiting for somebody to call me out on that.   :-)   ⁠ – G-Man Says 'Reinstate Monica' Jul 13 '17 at 06:03