You can't use ls
like that. Those *.[aA][vV][iI]
are expanded by the shell, not ls
, the -R
for ls
is for it to R
ecursively list the contents of directories, for which you need to pass it the path of directories, not files, and even then, it would output the list of files (any non-hidden files) in those directories without their directory components, so ffmpeg
could not find them.
Also, unless you use the --zero
option of very recent versions of the GNU implementation of ls
, the output of ls
is simply not post-processable reliably.
Here to find files with that list of extensions anywhere in the current working directory and below, you'd use find
. To store a list of files (or of anything for that matters), you use an array variable, not a string/scalar variable.
Using zsh
instead of bash
here would make it a lot easier as zsh has (properly working) recursive globbing and glob qualifiers which mean you can also restrict the list of files to those of type regular. Globs also skip hidden files by default (like ls
but not find
where you need to do that skipping by hand):
#! /usr/bin/zsh -
set -o extendedglob
videos=( **/*.(#i)(avi|mkv|mp4|vob)(N-.) )
play() {
print -ru2 Playing $argv
ffplay -hide_banner -infbuf -fs -sn -ast a:0 -- $argv
}
case $#videos in
(0) print -u2 No video found; exit 1;;
(1) play $videos;;
(*) print -u2 Select a video:
select video in $videos; do
play $video || exit
break
done;;
esac
With bash
(the GNU shell) + GNU find
, you could do something approaching with:
#! /usr/bin/bash -
readarray -td '' videos < <(
LC_ALL=C find . \
-regextype posix-extended \
-name '.?*' -prune -o \
-iregex '.*\.(avi|mkv|mp4|vob)' \
-xtype f \
-printf '%P\0' |
sort -z
)
shopt -u xpg_echo
play() {
echo>&2 -E Playing "$@"
ffplay -hide_banner -infbuf -fs -sn -ast a:0 -- "$@"
}
case ${#videos[@]} in
(0) echo>&2 No video found; exit 1;;
(1) play "${videos[@]}";;
(*) echo>&2 Select a video:
select video in "${videos[@]}"; do
play "$video" || exit
break
done;;
esac
Some other notes:
- Your
echo -e
would break for filenames that contain \
characters. Here you do not want the e
scape sequences to be expanded, hence the -E
for echo
or -r
for print
. If you want it to print an extra newline, add it to the last argument of echo
literally or with $'\n'
. Also note that bash
's echo
only accepts options if either the posix
or xpg_echo
is unset (and they are set by default on some systems and/or some environments). Generally, using echo
is best avoided, I still use it here for its ability to easily print its arguments joined with spaces (which is more cumbersome to do with printf
, and bash only has print
as a loadable plugin whose few systems have included by default when they have bash at all) and on the ground that we know the shell is bash
, so the play
function could be used to play more than one video at a time.
- Prompts and user messages should generally go to stderr (fd 2). That's where
select
's output goes for instance.
- The syntax to read a line is
IFS= read -r line
, not read line
. But in any case, file paths don't have to be made of a single line, as the newline character is as valid as any in a file name.
- note that your
*.[mM][kKpP][vV4]
would also match on files.mv4
(not m4v
).
ls
doesn't work like that and you can't really parse the output ofls
reliable. Usefind ... -print0
and arrays (readarray -td ''
in bash) or zsh and its recursive globs with qualifiers instead – Stéphane Chazelas Aug 22 '23 at 08:41ls
, chances are you are approaching the problem incorrectly.find
is usually what you want instead, possibly plus some post-processing of the file names or some calls tostat
to get the data you want. – Austin Hemmelgarn Aug 22 '23 at 19:24-R
option? That's for recursing into subdirectories. – Barmar Aug 23 '23 at 13:38-R
is not necessary. Sometimes I have directories of many seasons of a TV series - in that case I find that useful. – John Smith Aug 23 '23 at 18:19-x
is your friend! Also using shell arrays (in BASH) is probably more reliable (likearray=($(ls -R | grep 'your pattern'))
;${#array[*]}
is the number of items). – U. Windl Aug 24 '23 at 09:18