Search code examples
bashyoutube-dl

youtube-dl get channel / playlist name and pass it to bash one line script


I'm trying to download an entire Youtube channel and that worked.

But I'm having the directories' names like below and thus I need to change that all manually.

I need a way to pass channel / playlist name and id to the script instead of fetching the url.

Script I used :

# get working/beginning directory
l=$(pwd);
clear;
# get playlists data from channel list
youtube-dl -j --flat-playlist \
  "https://www.youtube.com/channel/UC-QDfvrRIDB6F0bIO4I4HkQ/playlists" \
  |cut -d ' ' -f4 \
  |cut -c 2-73 \
  |while IFS= read -r line;
  do;
    # loop: do with every playlist link
    # make a directory named by the playlist identifier in url
    mkdir ${line:38:80};
    # change directory to new directory
    cd $l/${line:38:80};
    # download playlist
    youtube-dl -f mp4 "$line";
    # print playlist absolute dir to user
    pwd;
    # change directory to beginning directory
    cd $l;
  done;

Names of directories :

.
├── PLxl69kCRkiI0oIqgQW3gWjDfI-e7ooTUF
├── PLxl69kCRkiI0q0Ib8lm3ZJsG3HltLQDuQ
├── PLxl69kCRkiI1Ebm-yvZyUKnfoi6VVNdQ7
├── ...
└── PLxl69kCRkiI3u-k02uTpu7z4wzYLOE3sq


This is not working :

  1. https://github.com/ytdl-org/youtube-dl/issues/23442

    # any playlist is seen as private
    youtube-dl -J \
      https://m.youtube.com/playlist?list=PL3GeP3YLZn5jOiHM8Js1_S0p_5HeS7TbY \
      | jq -r '.title'
    
  2. How to use youtube-dl from a python program?

    I need it for bash script not for python


Edit: simply explained

How to get channel name from bash youtube-dl and replace it with list id for file name in this script


Solution

  • Consider the following:

    #!/usr/bin/env bash
    
    # if we don't delete slashes from titles there are serious security issues here
    slash=/
    
    # note that this url, being in quotes, needs no backslash escaping.
    url='https://www.youtube.com/playlist?list=PLXmMXHVSvS-CoYS177-UvMAQYRfL3fBtX'
    
    # First, get the name for the whole playlist
    playlist_title=$(youtube-dl -J --flat-playlist "$url" | jq -r .title) || exit
    
    # ...and, for the rest of the script, work under a directory named by that title
    mkdir -p -- "${playlist_title//$slash/}" || exit
    cd "${playlist_title//$slash/}" || exit
    
    # Finally, loop over the individual videos and download them one at a time.
    # ...arguably, you could tell youtube-dl to do this itself; call it an exercise.
    youtube-dl -j --flat-playlist "$url" |   # one JSON document per playlist entry
      jq -r '[.id, .title] | @tsv' |         # write id, then title, tab-separated
      while IFS=$'\t' read -r id title; do ( # read that id and title from jq
          # because of the ()s, this is a subshell; exits just go to the next item
          # ...which is also why exec doesn't end the entire script.
          dir=${title//$slash/} # take slashes out of the title to form directory
          mkdir -p -- "$dir" || exit
          cd -- "$dir" || exit  # if cd fails, do not download anything
          exec youtube-dl "$id" # exec is a minor perf optimization; consume subshell
      ); done
    

    Note:

    • We're using jq to convert the JSON to a more safely-readable format that we can parse without byte offsets.
    • The extra backslashes were removed from the URL to prevent the 404 error described in the comments to the question.
    • Putting the body of the loop in a subshell with parenthesis means that the cd inside that subshell is automatically reversed when the parenthesized section is exited.
    • We don't trust titles not to contain slashes -- you don't need someone naming their video /etc/sudoers.d/hi-there or otherwise placing files in arbitrarily-chosen places.
    • Note the use of "$dir" instead of just $dir. That's important; see shellcheck warning SC2086.