1

I have a few data files that provide filenames of songs in a proprietary fashion. Now I want to convert that data to m3u-files and make that available to all applications. I don't want to use something like a cronjob that generates the m3u-files as that's not as dynamic as I want it to be.

Therefore, I decided to use named pipes. My scenario looks like this:

-rw-rw-rw-+ 1 sjngm sjngm 33929  6. May 12:56 songstore-1.data
prw-r--r--  1 sjngm sjngm     0  6. May 18:38 songstore-1.data.m3u
-rw-rw-rw-  1 sjngm sjngm  7750  6. May 12:56 songstore-2.data
prw-r--r--  1 sjngm sjngm     0  6. May 18:38 songstore-2.data.m3u
:

The script to do one run for one file seems to do its job nicely:

#/bin/bash

file="$1"

echo "#EXTM3U"

paste -d '\n' \
  <(tail -n +4 "$file" | grep "^#DESCRIPTION" | sed -e 's/#DESCRIPTION /#EXTINF:0,/') \
  <(tail -n +4 "$file" | grep "^#SERVICE" | cut -d ':' -f 11 | sed -e 's/%3a/:/gi')

This is the shell-script code that in the end should be stored in ~/.xprofile:

cd ~/garage/songstores
ls -1 songstore-* |
  paste - - |
  while read in pipe; do
    echo "$in..."
    while true; do
      ~/shell-scripts/convert.sh "$in" > "$pipe"
    done &
  done

After running this the loops show up in ps. When I cat one m3u the output appears many more times rather than just once. One songstore-file is actually empty and the output is:

$ cat songstore-13.data.m3u
#EXTM3U
#EXTM3U
#EXTM3U
#EXTM3U
#EXTM3U
#EXTM3U
#EXTM3U
#EXTM3U
#EXTM3U
#EXTM3U
#EXTM3U
#EXTM3U
#EXTM3U
#EXTM3U
#EXTM3U
#EXTM3U
#EXTM3U
#EXTM3U
#EXTM3U
#EXTM3U
#EXTM3U
#EXTM3U
$

The next time I execute the cat the number of lines is different, but always more than one. The idea is that the cat results in just one display of the content.

Again, the script itself works when run in a single execution on the command line. The problem must be in connection with the pipes and how I write to (or maybe read from) them.

What didn't I understand there and how do I fix it?

  • This doesn't seem to have anything to do with named pipes. Your inner loop (while true) will keep executing ~/shell-scripts/convert.sh "$in" > "$pipe" for as long as true is true. Your outer loop could be better written for f in songstore-*.data; do ~/shell-scripts/convert.sh "$f" "$f.m3u"; done - there's really no need to parse the output of ls -1 and try to cobble pairs of files together using paste. Beyond that, I don't understand what your script is supposed to do. – steeldriver May 6 '17 at 21:20
  • @steeldriver Thanks for the input regarding the outer loop – sjngm May 11 '17 at 16:45
0

Two things:

1) I applied a sleep to the outer loop script:

for f in /home/sjngm/garage/songstores-*.data; do
  echo "$f..."
  while true; do
    /home/sjngm/shell-scripts/convert.sh "$f" > "$f.m3u"
    sleep 2
  done &
done

2) In case anyone wants to do this: it doesn't seem to work to use process substitution when already trying to write into a named pipe. Hence, the old fashioned way using temporary files helps here:

#/bin/bash

file="$1"
tmpFile1="/tmp/`uuidgen`"
tmpFile2="/tmp/`uuidgen`"

tail -n +4 "$file" | grep "^#DESCRIPTION" | sed -e 's/#DESCRIPTION /#EXTINF:0,/' > $tmpFile1
tail -n +4 "$file" | grep "^#SERVICE" | cut -d ':' -f 11 | sed -e 's/%3a/:/gi' > $tmpFile2

echo "#EXTM3U"
paste -d '\n' $tmpFile1 $tmpFile2

rm $tmpFile1 $tmpFile2

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.