1

I'm trying to set how long nvlc will run. There are actually multiple nvlc commands in a case statement so I can choose the stream to play. I've posted the script as a gitlab snippet here.

I want to either set a duration or if $duration is unset or set to 0, the 'timeout (duration)s' (s for seconds or m for minutes) will not be added before 'nvlc'

read -p "What duration in MINUTES do you want the recording to run for? :  " duration
if [ -z ${duration+x} -o $duration = 0 ]; then t=""; else t='timeout '"$duration"'m'; fi

and later (on line 47 and other lines) nvlc is called like:

"$t" nvlc stream-url

So if duration is unset or set to 0, then "$t" is just whitespace, but if a value is set for duration, the duration variable will be interpreted in the nvlc command, like: timeout 60m nvlc stream-url

I'm getting various errors. With t='timeout '"$duration"'s' the error is: line 47: timeout 5s: command not found

With t='timeout $durations' the error is: line 47: timeout $durations: command not found

Can you point out where I'm going wrong please?

2
  • Variables are not expanded in single quotes. See mywiki.wooledge.org/BashFAQ/050
    – l0b0
    Commented Dec 13, 2020 at 7:37
  • @Archemar I tried that last night (the approach you'd mentioned in another comment). It didn't work but I'll have to try it again to reproduce the error or how it hangs. Thanks for pointing out the double brackets. The single brackets just call the literal string instead of expanding the value for ${duration}. I believe I had tried to surround -duration- in regular brackets and it didn't work, possibly because when I called $t in the vlc command, it had double quotes around it (which Gordon pointed out won't work in this particular use case).
    – oksage
    Commented Dec 13, 2020 at 17:42

1 Answer 1

3

There are a couple of problems here. The first is that you're expanding $t in double-quotes:

"$t" nvlc stream-url

Double-quoting variable references is almost always a good idea, since it prevents unexpected word splitting and/or wildcard expansion, but in this case you need word splitting. If t is set to timeout 5s, the double quotes make the shell treat the entire string as the command name, rather than splitting it into timeout (the command name) and 5s (an argument to it). Also, if t is set to the empty string, it doesn't just vanish from the command, it actually tries to run the empty string as the command name! To solve this, just remove the double-quotes:

$t nvlc stream-url

(If the command were more complex, you might need to use an array instead of a plain variable; see BashFAQ #50: I'm trying to put a command in a variable, but the complex cases always fail!)

The second problem is the conditional expression [ -z ${duration+x} -o $duration = 0 ]. Since the references to the duration variable are not double-quoted here, they do vanish if duration is set to the empty string, so the whole thing will expand to [ -z x -o = 0 ], which is not valid. Here, you need to double-quote them. And also either remove the +x from the first test, or replace it with :+x -- the +x option makes it expand to "x" if the variable is set at all (even if it's set to the empty string), but since it was just read it'll always expand to "x". Just remove the +x and add proper double-quotes:

if [ -z "${duration}" -o "$duration" = 0 ]; then ...

Finally, the quoting in t='timeout '"$duration"'m' is weird. Not really wrong, just overcomplicated. Single-quoting the non-variable sections is overkill, and single-quoting the whole thing will prevent the variable from being expanded. It'd be simpler and clearer to just double-quote the whole thing:

t="timeout ${duration}m"

(Note that the braces are needed so "m" (or "s" as you have in some versions) isn't treated as part of the variable name.)

5
  • I've read what you've written and am trying to 'get' what you're saying before just copying/pasting. I see what you're saying about double quoting $t when calling it. So for $t, no double quotes means it will 'disappear' when the variable is not set. And vice versa for using the double quotes in the test: [ -z "${duration}" -o "$duration" = 0 ] . I've also changed the way the $t variable was assigned. When I run the command, vlc just hangs and shows one line instead of the whole nvlc interface (ncurses). The line is: VLC media player 3.0.11.1 Vetinari (revision 3.0.11.1-0-g52483f3ca2)
    – oksage
    Commented Dec 13, 2020 at 17:52
  • While vlc hangs, there is no file produce yet. When I try to use Ctrl-c to kill vlc, it won't kill it. It just outputs ^C below the vlc line. I close the terminal and then a 0 byte file with the proper name appears in the directory. The file has the icon of a file, even thought it has the .mp3 extension. I then open another terminal and pkill -9 vlc , just in case. I wonder if you're onto something with your comment about the command being more complex. Perhaps that is the problem. I've posted the script on gitlab. I'll add the link in the question (at the end of the first paragraph).
    – oksage
    Commented Dec 13, 2020 at 18:00
  • 1
    @oksage When run from a shell script, timeout treats the command it's running (nvlc in this case) as a background job, meaning it'll be stopped if it tried to read from the terminal. Which it does. Use timeout --foreground (i.e. t="timeout --timeout ${duration}m") to avoid this. Also, the test for whether a delay was entered (line 25) has the same problem I described with the test on duration, so apply the same solution: add double-quotes and remove +x. Commented Dec 15, 2020 at 1:00
  • In the original script it didn't work when entering HH:MM format but it did when I entered just seconds (3600 for an hour or w.h.y.). So I've changed it so the HH:MM>seconds conversion just echos the output and then I manually enter the seconds with read. This will eliminate that as a possible failure point and I may change it later once the duration functionality works. I've also moved the delay lines into the countdown function for readability. There was also another problem with delay that I missed, other than what you pointed out. Added --foreground to timeout.
    – oksage
    Commented Dec 15, 2020 at 20:15
  • Gordon, it works! You rock.
    – oksage
    Commented Dec 15, 2020 at 20:35

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .