1

When I run the below script mplayer gives the below error and doesn't continue the while loop after pressing return. if I replace mplayer with mpv it works. I have to use mplayer, as mpv doesn't support the video formats I need to play.

I suspect the problem is related to file descriptor redirection, but I had to do that to get user input to work in a while loop with piped data from find.

Purpose

The goal of the script is I want to play each file in a directory, and after watching the video it should prompt me for what to do with the file. E.g. delete, rename, move.

Question

Can anyone see what the problem is, or perhaps how to work around it?

#!/usr/bin/bash

exec 3<&0 # redirect std input to a different file descriptor
find . -maxdepth 1 -type f -name "*" | while read f; do

mplayer -really-quiet -msglevel all=-1 "$f"

echo $f
printf "What to do: "
IFS= read -r -u3 opt

done
exec 3<&- # Close fd3

The error is

do_connect: could not connect to socket
connect: No such file or directory
Failed to open VDPAU backend libvdpau_va_gl.so: cannot open shared object file: No such file or directory
Assertion 'm' failed at pulse/thread-mainloop.c:175, function pa_threaded_mainloop_lock(). Aborting.
Sandra Schlichting
  • 25,050
  • 33
  • 110
  • 162
  • 1
    I have no idea about mplayer internal but in my understanding you are just looping on the files you find in your directory right? I don't understand why your loop is so complex! Would it be impossible to just do `for f in $(find . -maxdepth 1 -type f -name '*'); do ...; done;` and avoid the redirection of std? Let me know if it works! – Allan May 02 '18 at 07:24
  • Just run `find . -maxdepth 1 -type f -name '*' -print0 | xargs -0 mplayer -really-quiet -msglevel all=-1` and it should work fine for the space issue (no loop anymore, remove the `for` construction) – Allan May 02 '18 at 07:43
  • 2
    the syntax to loop over files in current directory is just `for f in *; do [[ -f $f ]] || continue; ... ;done`, this will work with any character in filenames including spaces, only in command calls must use quotes `"$f"` as it's already done – Nahuel Fouilleul May 02 '18 at 08:14
  • 1
    By default, `read` will interpret backslashes before spaces and line feeds, and otherwise strip them — This is rarely expected or desired. Normally you just want to read data, which is what `read -r` does. You should always use `-r` unless you have a good reason not to. – l'L'l May 02 '18 at 08:30
  • @NahuelFouilleul That did the trick. Can you post it as an answer? – Sandra Schlichting May 02 '18 at 08:59

1 Answers1

1

Changed to answer from comment, shell syntax to loop over files in current directory is just :

for f in *; do
    [[ -f $f ]] || continue
    ... do something with "$f"
done

This will work with any character in filenames including spaces.

The -f test is to ensure $f is a file (otherwise continue).

This handles also the case where there is no file : glob is not expanded and "$f" is "*".

The issue with mplayer may be due to the pipe writing to standard input of while .. done as to mplayer input is inherited from caller if mplayer is consuming whole input the caller will have an empty input. another fix could be to explicitly redirect input inside while loop exec 0</dev/null or just for mplayer's command mplayer .. </dev/null. or just exec 0</dev/tty and in this last case exec 3<&0/read -r -u3 opt is no more needed just read -r opt

Nahuel Fouilleul
  • 18,726
  • 2
  • 31
  • 36