Skip to content

Instantly share code, notes, and snippets.

@Ultrabenosaurus
Last active December 20, 2020 23:33
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save Ultrabenosaurus/8974206b2cba0f1c615a to your computer and use it in GitHub Desktop.
Save Ultrabenosaurus/8974206b2cba0f1c615a to your computer and use it in GitHub Desktop.
ytsearch - search and launch YouTube videos from bash!
#!/bin/bash
# ytsearch
# original: https://coderwall.com/p/jvuzdg
# created by: Balazs Nadasdi <http://about.me/yitsushi>
# this version: https://gist.github.com/Ultrabenosaurus/8974206b2cba0f1c615a
# edited by: Dan Bennett <http://about.me/d.bennett>
# license: BSD 3-Clause <http://opensource.org/licenses/BSD-3-Clause>
#
# converted to a script for easier redistribution and development
# expanded to perform both searching and providing of URLs
#
# todo:
# * get `-w` to launch the URL in the user's default browser rather than echo?
# * add another flag for passing in a command name, pipes output of `-w` to the command
# * figure out a way of not requiring re-entering search terms for `-w` usage
#
# options:
# -h
# print this help text in your terminal
# -s "search term"
# do a search for the "search term"
# shows a list of numbers and titles, use the number with `-w` to watch the video
# -w n "search term"
# get URL for the nth video in the list of search results
# currently uses `echo`, need to get this tested on other environments
# consolidate help text to a single location to minimise inconsistencies
ytsearch_help(){
printf "%s\n" "ytsearch"
printf "%s\n" "original: https://coderwall.com/p/jvuzdg"
printf "%s\n" "created by: Balazs Nadasdi <http://about.me/yitsushi>"
printf "%s\n" "this version: https://gist.github.com/Ultrabenosaurus/8974206b2cba0f1c615a"
printf "%s\n" "edited by: Dan Bennett <http://about.me/d.bennett>"
printf "%s\n\n" "license: BSD 3-Clause <http://opensource.org/licenses/BSD-3-Clause>"
printf "%s\n" "converted to a script for easier redistribution and development"
printf "%s\n\n" "expanded to perform both search and launching of videos"
printf "%s\n" "todo:"
printf "\t%s\n" "* get \`-w\` to launch the URL in the user's default browser rather than echo?"
printf "\t%s\n" "* add another flag for passing in a command name, pipes output of \`-w\` to the command"
printf "\t%s\n\n" "* figure out a way of not requiring re-entering search terms for \`-w\` usage"
printf "%s\n" "options:"
printf "\t%s\n" "-h"
printf "\t\t%s\n" "print this help text in your terminal"
printf "\t%s\n" "-s \"search term\""
printf "\t\t%s\n" "do a search for the \"search term\""
printf "\t\t%s\n" "shows a list of numbers and titles, use the number with \`-w\` to watch the video"
printf "\t%s\n" "-w n \"search term\""
printf "\t\t%s\n" "watch the nth video in the list of search results"
printf "\t\t%s\n" "currently uses \`echo\`, need to get this tested on other environments"
exit
}
# catch no-parameter usage
if [ -z $1 ]; then
ytsearch_help
fi
# apparently Linux doesn't have -r flag for sed...
sed_r(){
DIST="linux"
case `uname -s` in
"Darwin")
DIST="mac"
;;
"$(expr substr $(uname -s) 1 10)")
DIST="win"
;;
esac
while getopts ":wt" opt; do
case $opt in
w)
if [ $DIST == "win" ]; then
echo sed -r -e 's/^watch\?v=([^"]*)".*/\1/g'
else
echo sed -e 's/^watch\?v=\([^"]*\)".*/\1/g'
fi
;;
t)
if [ $DIST == "win" ]; then
echo sed -r -e 's/^.*title="(.*)/\1/g'
else
echo sed -e 's/^.*title="\(.*\)/\1/g'
fi
;;
esac
done
}
# main functionality
while getopts ":hw:s:" opt; do
case $opt in
h)
ytsearch_help
;;
w)
oldifs="$IFS"
IFS=$'\n'
searchResults=($(curl -s https://www.youtube.com/results\?search_query\=$3 | \
grep -o 'watch?v=[^"]*"[^>]*title="[^"]*' | \
sed_r -w))
IFS="$oldifs"
echo "http://youtube.com/watch?v=${searchResults[$OPTARG-1]}"
exit
;;
s)
oldifs="$IFS"
IFS=$'\n'
searchResults=($(curl -s https://www.youtube.com/results\?search_query\=$OPTARG | \
grep -o 'watch?v=[^"]*"[^>]*title="[^"]*' | \
sed_r -t))
IFS="$oldifs"
for i in "${!searchResults[@]}"; do
num=`expr $i + 1`
printf " %s\t\t%s\n" "$num" "${searchResults[$i]}"
done
exit
;;
\?)
printf "Invalid option: -%s\n\n" "$OPTARG"
ytsearch_help
;;
:)
printf "Option -%s requires an argument\n\n" "$OPTARG"
ytsearch_help
;;
*)
ytsearch_help
;;
esac
done
@yitsushi
Copy link

I tested there is no -r flag for sed =/ So it solves the problem for Windows but broke Linux/Mac.

sed: illegal option -- r

There is some suggestion:

Without a single parameter

if [[ -z $1 ]]; then
  ytsearch_help
  exit
fi

Check OS

DIST="linux"
case `uname -s` in
  "Darwin")
    DIST="mac"
    ;;
  "$(expr substr $(uname -s) 1 10)")
    DIST="win"
    ;;
esac

So if you put the parse section into a separated function then you can test it if [[ $DIST == "win" ]].

@Ultrabenosaurus
Copy link
Author

Thanks! I was wondering why running just ytsearch didn't print the help text, from reading about it online I thought the * case should handle it - I put it down to a Windows bug. Will add that block above the while.

Question: does exit not close the terminal window? I thought it did...

That's weird, the Windows install of Git Bash lists this under sed --help:

-r, --regexp-extended
               use extended regular expressions in the script.

I'll amend the script to detect Windows, thanks for pointing it out! Not sure if detecting Mac is necessary, but I'll leave that in for if I have to change sed usage again after I get someone to test on a Mac for me.

@Ultrabenosaurus
Copy link
Author

Okay, so I've now updated it as above but I've done something wrong and I have no idea what it is. Is there something special you have to do inside functions to receive piped input? All I'm getting as the output is this:

o_O? ytsearch -s "cheese"
C:\Program Files (x86)\Git\bin\grep.exe: writing output: Invalid argument
C:\Program Files (x86)\Git\bin\grep.exe: writing output: Invalid argument
C:\Program Files (x86)\Git\bin\grep.exe: writing output: Invalid argument

I assume writing output: Invalid argument means that grep doesn't like what it's being piped into, which would be sed_r -t for a search:

oldifs="$IFS"
IFS=$'\n'
searchResults=($(curl -s https://www.youtube.com/results\?search_query\=$OPTARG | \
    grep -o 'watch?v=[^"]*"[^>]*title="[^"]*' | \
    sed_r -t))            # this bit
IFS="$oldifs"
for i in "${!searchResults[@]}"; do
    num=`expr $i + 1`
    printf "    %s\t\t%s\n" "$num" "${searchResults[$i]}"
done
exit

@loretoparisi
Copy link

It seems does not end up with any output on macOS Sierra.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment