2

I am writing a bash script to convert lyrics to audio clips using espeak. The problem is that espeak only says the first word, rather than the line by line that I'm reading. I tried putting the lines in the file with quotes, but this did not fix the problem.

Here is my bash script:

#!/bin/bash
input="$1"
##input="/path/to/txt/file"
while IFS= read -r line
do
  echo "$line"
  espeak -k cantonese $line

done < "$input"

Here is the text file line by line:

"Work it"
"Make it"
"Do it"
"Make us"
"Harder"
"Better"
"Faster"
"Stronger"

How can I make espeak say every word?

Please note that every word is said, when I read from a file using the -f option.

Eliah Kagan
  • 119,640
j0h
  • 15,365

1 Answers1

3

Instead of:

espeak -k cantonese $line

Use:

espeak -k cantonese "$line"

When you omit the double quotes around $line, the shell performs word splitting on the result of parameter expansion, and each word is passed as a separate command-line argument to espeak. The espeak command only speaks the first argument. Writing "$line" instead of $line suppresses word splitting, causing all the text stored in the line parameter to be passed as a single argument to espeak. (It also suppresses globbing, which is another thing you don't want to happen in this situation, though your test inputs have most likely not triggered it so far.)

This happens even in simpler uses of espeak. For example, espeak hello world says just "hello," while espeak 'hello world' or espeak "hello world" says "hello world."

As for what kind of quotes to use, the reason to write "$line", rather than than '$line', is that single quotes are too powerful for what you need. They would suppress word splitting and globbing, but they would also suppress parameter expansion. So with '$line', the espeak command would see the literal text $line instead of whatever text is held in the line parameter.

Eliah Kagan
  • 119,640