2

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

  • Remember about quotes. Rule of a thumb: every time you do `$var` add quotes `"$var"`. `not working` - what does it mean it's "not working"? I don't understand, what exactly do you want to pass to your script? Can you give an example? You want to pass `PL3GeP3YLZn5jOiHM8Js1_S0p_5HeS7TbY` and in result your script scould know the channel name? How is the `not working` code snipped related? – KamilCuk Jan 09 '20 at 12:33
  • thought that also – Abd-Elaziz Sharaf Jan 09 '20 at 13:51
  • 2
    `$ youtube-dl -J --no-warnings "https://www.youtube.com/playlist\?list\=PLXmMXHVSvS-CoYS177-UvMAQYRfL3fBtX" | jq -r '.title'` – Abd-Elaziz Sharaf Jan 09 '20 at 13:51
  • `ERROR: Unable to download webpage: HTTP Error 404: Not Found (caused by ); please report this issue on https://yt-dl.org/bug . Make sure you are using the latest version; see https://yt-dl.org/update on how to update. Be sure to call youtube-dl with the --verbose flag and include its complete output.` – Abd-Elaziz Sharaf Jan 09 '20 at 13:52
  • 1
    Ever notice how hard a really long one-line script can be to debug? If this script is useful over time, you will curse the person who wrote it as you do the necessary maintenance. Stay on the right side of future you and break this script into testable functions. – Mike Slinn Apr 17 '21 at 23:54
  • I have commented the code so you could understand it.. the only problem with me is to get playlist name from url as I really don't no what is the staff downloaded, thanks for refreshing question @MikeSlinn – Abd-Elaziz Sharaf Apr 18 '21 at 01:37
  • The backslashes in your string would be necessary if it _wasn't_ in quotes. `"?"` is fine as it is, there's no reason for it to be `"\?"` (and some good reasons for it not to be, because quotes in that context don't have well-defined behavior). – Charles Duffy Apr 18 '21 at 01:37
  • I appreciate the effort taken for the comments, but they are not helpful to someone who knows bash. The rule for comments is "assume the reader is reasonably competent", unless there is a reason to suspect otherwise. – Mike Slinn Apr 18 '21 at 01:40
  • I was trying to get you to think of applying structure to the code, so it is easy to work with. A long chain like this is brittle and easily broken. Two weeks from now you will find it much more difficult to fix than you do today. – Mike Slinn Apr 18 '21 at 01:42
  • I'd argue that the `cut` use is the most brittle thing here. Unless `youtube-dl` has a documented promise to maintain specific column offsets in its output, there's no reason to expect them to be consistent across runs, particularly in presence of version updates, new/different test data, etc. – Charles Duffy Apr 18 '21 at 01:47
  • (It would also reduce room for errors to move the `cd` into a subshell so it can be implicitly undone when that subshell exits instead of needing to change directories back, but that's relatively minor). – Charles Duffy Apr 18 '21 at 01:48
  • ...to be clear: When I take out the extra backslashes, I can't reproduce the 404 from the `youtube-dl -J | jq` approach. That is to say, `youtube-dl -J "https://www.youtube.com/playlist?list=PLXmMXHVSvS-CoYS177-UvMAQYRfL3fBtX" | jq -r '.title'` does not cause the stated error when I try it myself. – Charles Duffy Apr 18 '21 at 02:09

1 Answers1

3

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.
Charles Duffy
  • 280,126
  • 43
  • 390
  • 441