1

I am trying to attach multiple files in Unix, which are the result of a find command. When I try to send the mail, the attachments are missing.

dir=$path
echo "Entered into $spr/sum_master"
for fil in `find $dir -ctime -2 -type f -name "Sum*pdf*"`
do
  uFiles=`echo "$uFiles ; uuencode $fil  $fil"`
done
\($uFiles\) | mailx -s "subject" abc@gmail.com

What is wrong with this code?

  • $uFiles will be empty after exiting for loop because for runs subshell – dchirikov Jun 20 '14 at 14:09
  • what is the content of path? should it be $PATH? – polym Jun 20 '14 at 17:58
  • path=/home/as12345/bills – Aravind Jun 21 '14 at 4:46
  • @dchirikov No, loops do not run in a subshell. It's things like pipes, substitutions, etc. that introduce subshells. – Gilles Jun 21 '14 at 9:17
0

If uFiles ends up containing the string foo bar qux, then the last line runs the command (foo with the arguments bar and qux). This results in the error message (foo: command not found (or similar), and mail gets an empty input.

That's not the only problem with the script. The command that builds up the uFiles variable doesn't do at all what you think it does. Run bash -x /path/to/script to see a trace of the script, it'll give you an idea of what's happening. You're echoing the uuencode command instead of running it. You don't need echo there:

  uFiles="$uFiles
  $(uuencode "$fil" "$fil")"

That will make the loop work, but it's brittle; in particular, it will break on file names containing spaces and other special characters (see Why does my shell script choke on whitespace or other special characters? for more explanations). Parsing the output of find is rarely the easiest way to do something. Instead, tell find to execute the command you want to execute.

find "$dir" -ctime -2 -type f -name "Sum*pdf*" -exec uuencode {} {} \;

The output of that is the concatenation of the uuencoded files that you were trying to build. You can pass it as input to mail directly:

find "$dir" -ctime -2 -type f -name "Sum*pdf*" -exec uuencode {} {} \; |
mailx -s "subject" abc@gmail.com

If you want to detect potential failures of the uuencode step, you can stuff it into a variable (but beware that it might be very big):

attachments=$(find "$dir" -ctime -2 -type f -name "Sum*pdf*" -exec uuencode {} {} \;)
if [ $? -ne 0 ]; then
  echo 1>&2 "Error while encoding attachments, aborting."
  exit 2
fi
if [ -z "$attachments" ]; then
  echo 1>&2 "Notice: no files to attach, so mail not sent."
  exit 0
fi
echo "$attachments" | mailx -s "subject" abc@gmail.com

Alternatively, write a temporary file.

attachments=
trap 'rm -f "$attachments"' EXIT HUP INT TERM
attachments=$(mktemp)
find "$dir" -ctime -2 -type f -name "Sum*pdf*" -exec uuencode {} {} \; >"$attachments"
if [ $? -ne 0 ]; then
  echo 1>&2 "Error while encoding attachments, aborting."
  exit 2
fi
if ! [ -s "$attachments" ]; then
  echo 1>&2 "Notice: no files to attach, so mail not sent."
  exit 0
fi
mailx -s "subject" abc@gmail.com <"$attachments"

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.