0

I am using at in coordination with notify-send/dunst as a form of reminders for myself. In an interactive bash session, doing:

$ echo 'notify-send "Test"' | at 12:45PM

works just fine and I see the notification pop up at exactly 12:45PM as expected. However, in a script like:

$ cat ~/.local/bin/remind
#!/bin/bash

echo 'notify-send "$1"' | at "$2"

$ remind "Test" "12:45PM"

I don't see the notification pop up.

The job is registered with at, as seen by:

$ at -l

so I'm not sure what the problem could be. notify-send works just fine outside of the script, and at has correctly found the job, but I still don't see a popup when trying with the second method.

Any ideas?

ThoseKind
  • 105

1 Answers1

2

There are two levels of interpretation:

  1. bash running your script interprets the whole command. Here $1 is single-quoted, so it is not expanded. The string containing literal "$1" gets to at.

  2. When the time comes, at runs the previously echoed string using sh. Now $1 is double-quoted and it gets expanded to an empty string because this sh apparently runs without arguments. Whatever you provided to the script is long gone. The final command is as if you typed notify-send "" in a shell. Run it and see what happens.

A basic fix is to swap the quotes:

echo "notify-send '$1'" | at "$2"

This way bash will expand $1 and the result will be single-quoted later, when sh runs. The approach is not very robust; the code will break if you inject a single quote. Yet in many cases it will work.


A more robust way is like this:

#/bin/bash

t="$1"
shift
m="$*"

<<<"notify-send ${m@Q}" at "$t"

The main point is using the ${variable@Q} syntax. It makes Bash expand the variable and properly single-quote the result, so it can be safely parsed later (by sh in this case).

Note I obtain time from the first argument. The idea is to be able to call the script without inconvenient quotes, like this:

remind 15:10 Go to Yuma