help-bash
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Can't find file


From: Greg Wooledge
Subject: Re: Can't find file
Date: Tue, 12 Nov 2019 09:30:31 -0500
User-agent: Mutt/1.10.1 (2018-07-13)

On Mon, Nov 11, 2019 at 08:24:58PM -0500, David Niklas wrote:
> I'm trying to automate the locating and playing of files with subtitles
> that are separate from the video.
> 
> I've placed this into my .bashrc:
> 
> function mpv-subtitle()
> {
>     # Have mpv play files with subtitles.
>     if [ $# -eq 0 ]; then
>         echo -e "mpv-subtitle FILES.FORMAT\n\n\tPlays files with their 
> subtitles.";
>         return 0;
>     fi
> 
>     for i in "$@"; do
>         mpv --title="window title" --pause --profile opengl-hq 
> --scale=ewa_lanczossharp \
>             --deband-iterations=5 --cache=8192 --volume=100 --volume-max=200 \
>             --audio-device=alsa/dixy \
>             $(awk -v z="$i" 'BEGIN{ sub(/\.(avi|ogv|mpe?g|mkv|mp4|webm)/,
>             "", z); ret = system("test -f \"" z ".en.vtt\""); if(ret ==
>             0){ print "--sub-file " z ".en.vtt" } ret = system("test -f
>             \"" z ".srt\""); if(ret == 0){ print "--sub-file " z
>             ".srt" } }' ) \ "$i"; done }

Good lord.

If this thing writes one filename to stdout, then what you want to do
is enclose the entire command substitution in double quotes.

mpv --blah "$(awk ...)"

That ONLY works if the awk command writes ONE FILE NAME and nothing
else (except possibly a trailing newline).

> When I invoke it on a file without spaces it works like a charm:

https://mywiki.wooledge.org/Quotes

OK, problem solv--

> I can't quote the $(...) because I need to pass the --sub-file FILE as
> separate arguments.

GAAAHHHH.

Does this awk command write SOMETHING OTHER THAN ONE FILE to stdout?

What does it DO?

If it attempts to write a LIST OF SHELL ARGUMENTS to standard output,
then you need to take an ENTIRELY different approach to this problem.

Let's speculate that "the awk command writes a series of shell
arguments like --foo -b -a -r to stdout, and I want to use them as
arguments in my mpv command".

In THAT case, what you need to do is serialize this list of shell
arguments in a way that bash can parse (deserialize) into an array.
Then expand the array to generate the arguments of mpv.

The easiest way to handle this would be to have the awk command
write one argument (array element) per line, and then capture them
in an array using newlines as delimiters:

myfunc() {
  local i args
  for i; do
    mapfile -t args < <(awk command from hell which writes one arg per line)
    mpv --static --arguments "${args[@]}"
  done
}

This will fail if any of your arguments (filenames) contains a newline
character, because the newline character will be seen as an array
delimiter by mapfile.

If that's a concern, then you'll need to use NUL delimiters instead of
newline delimiters.  Or, you could simply disallow filenames that
contain newline characters.

Another thing you might try is NOT using awk to generate this hypothetical
list of command-line arguments for mpv.  Why not simply generate the
arguments in bash?  Then you don't need the serialize/deserialize
steps.

/me looks at the awk command from hell one more time.

It appears that you're stripping the extension from each input filename
and looking for other files that have the same "base" part with
different extensions.  Bash is fully capable of doing that all on its
own, without calling awk.

myfunc() {
  local i args base
  for i; do
    args=()
    base=${i%.*}
    [[ -f $base.foo ]] && args+=(--foo "$base.foo")
    [[ -f $base.bar ]] && args+=(-b -a -r "$base.bar")
    ...
    mpv --static --arguments "${args[@]}" "$i"
  done
}

Maybe something like this?

There are lots of possibilities, but only someone who knows what the
actual goal is can decide the best one.

See also <https://mywiki.wooledge.org/BashFAQ/050>.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]