Skip to main content
added match for video file names. and forgot to increment episode_number ...
Source Link
Olivier Dulac
  • 6.6k
  • 1
  • 26
  • 42
  • a file "series_name.txt" where you put all the episode names in order, 1 per line
  • a script to which you give the arguments: "$HardlinkDir" "$dirA" "$dirB" "$dirC" (...)

a file "series_name.txt" where you put all the episode names in order, 1 per line. for exemple :

 s01e01 - Episode Name
 s01e02 - Episode Name
 etc.

And a script to which you give the arguments: "HardlinkDir" "series_name.txt" "dirA" "dirB" "dirC" (...)

#!/usr/bin/env bash
_usage() {
  cat <<'EOF'
   this script needs at least those arguments:
     # $1=HardLinkDir, $2=series_name.txt # containing 1 line per episode name
     # $3 to $n : the directory, in order, with the *.mp4 and *.mkv in them, in order
   it will then EMPTY the $1 directory, and re-create hard links (ln) in it.
EOF
   for msg in "$@"; do printf "Erreur: %s\n" "$msg" ; done
   exit 1
}

if [ "$#" -lt 3 ]; then
   _usage "We need at least 3 args : HardLinkDir series_name.txt dirA ... "
fi
lndir="$1" ; 
episode_list="$2" ; series_name="${2/.txt/}" ; 
[ -d "$lndir" ] || _usage "arg1 : lndir=$lndir : is not a directory"
[ -f "$episode_list" ] || _usage "arg2 : episode_list=$episode_list : is not a file"
shift 2 # we "absorbed" the first 2 args : the rest are the dirs with the movie files
arg=2
for dir in "$@"; do 
  arg=$((arg + 1))
  [ -d "$dir" ] || _usage "arg${arg}: '$dir' : is not a directory."
done  

rm "${lndir:-__must_be_nonvoid__}"/*  # delete first the files in that dir, if any

for dir in "$@"; do
  ls "${dir}"/*.???
done | awk -v series_name="${series_name}" -v lndir="${lndir}" '
 BEGIN { after_first=0 }
 (NR == FNR) { rem="we read the first file... so the episode list"
               episode[NR]=$0
 }

 ((NR != FNR) && ( after_first==0 )) { after_first=1; episode_number=0 }

 ((NR != FNR) && ( $0 ~ /..mp4|.mkv/ ) { 
   rem="NR>FNR, so we read the 2nd file, -, stdin..."
   rem="we also match .mp4 or .mkv, so we have a video file fullname as input"
   episode_number++
   fullfilename=$0; ext=fullfilename ; sub(".*[.]","",ext)
   destname = lndir "/" series_name " - " episode[episode_number] "." ext
   cmd="ln \"" fullfilename "\" \"" destname "\""
   printf("executing: %s\n",cmd)
   system(cmd); close(cmd)
 }
' "$episode_list" "-"  # first file is the episode_list file, then stdin
  • a file "series_name.txt" where you put all the episode names in order, 1 per line
  • a script to which you give the arguments: "$HardlinkDir" "$dirA" "$dirB" "$dirC" (...)
#!/usr/bin/env bash
_usage() {
  cat <<'EOF'
   this script needs at least those arguments:
     # $1=HardLinkDir, $2=series_name.txt # containing 1 line per episode name
     # $3 to $n : the directory, in order, with the *.mp4 and *.mkv in them, in order
   it will EMPTY the $1 directory, 
EOF
   for msg in "$@"; do printf "Erreur: %s\n" "$msg" ; done
   exit 1
}

if [ "$#" -lt 3 ]; then
   _usage "We need at least 3 args : HardLinkDir series_name.txt dirA ... "
fi
lndir="$1" ; 
episode_list="$2" ; series_name="${2/.txt/}" ; 
[ -d "$lndir" ] || _usage "arg1 : lndir=$lndir : is not a directory"
[ -f "$episode_list" ] || _usage "arg2 : episode_list=$episode_list : is not a file"
shift 2 # we "absorbed" the first 2 args : the rest are the dirs with the movie files
arg=2
for dir in "$@"; do 
  arg=$((arg + 1))
  [ -d "$dir" ] || _usage "arg${arg}: '$dir' : is not a directory."
done  

rm "${lndir:-__must_be_nonvoid__}"/*  # delete first the files in that dir, if any

for dir in "$@"; do
  ls "${dir}"/*.???
done | awk -v series_name="${series_name}" -v lndir="${lndir}" '
 BEGIN { after_first=0 }
 (NR == FNR) { rem="we read the first file... so the episode list"
               episode[NR]=$0
 }

 ((NR != FNR) && ( after_first==0 )) { after_first=1; episode_number=0 }

 ((NR != FNR) && ( $0 ~ /..mp4|.mkv/ ) { 
   rem="NR>FNR, so we read the 2nd file, -, stdin..."
   rem="we also match .mp4 or .mkv, so we have a video file fullname as input"
   episode_number++
   fullfilename=$0; ext=fullfilename ; sub(".*[.]","",ext)
   destname = lndir "/" series_name " - " episode[episode_number] "." ext
   cmd="ln \"" fullfilename "\" \"" destname "\""
   printf("executing: %s\n",cmd)
   system(cmd); close(cmd)
 }
' "$episode_list" "-"  # first file is the episode_list file, then stdin

a file "series_name.txt" where you put all the episode names in order, 1 per line. for exemple :

 s01e01 - Episode Name
 s01e02 - Episode Name
 etc.

And a script to which you give the arguments: "HardlinkDir" "series_name.txt" "dirA" "dirB" "dirC" (...)

#!/usr/bin/env bash
_usage() {
  cat <<'EOF'
   this script needs at least those arguments:
     # $1=HardLinkDir, $2=series_name.txt # containing 1 line per episode name
     # $3 to $n : the directory, in order, with the *.mp4 and *.mkv in them, in order
   it will then EMPTY the $1 directory, and re-create hard links (ln) in it.
EOF
   for msg in "$@"; do printf "Erreur: %s\n" "$msg" ; done
   exit 1
}

if [ "$#" -lt 3 ]; then
   _usage "We need at least 3 args : HardLinkDir series_name.txt dirA ... "
fi
lndir="$1" ; 
episode_list="$2" ; series_name="${2/.txt/}" ; 
[ -d "$lndir" ] || _usage "arg1 : lndir=$lndir : is not a directory"
[ -f "$episode_list" ] || _usage "arg2 : episode_list=$episode_list : is not a file"
shift 2 # we "absorbed" the first 2 args : the rest are the dirs with the movie files
arg=2
for dir in "$@"; do 
  arg=$((arg + 1))
  [ -d "$dir" ] || _usage "arg${arg}: '$dir' : is not a directory."
done  

rm "${lndir:-__must_be_nonvoid__}"/*  # delete first the files in that dir, if any

for dir in "$@"; do
  ls "${dir}"/*.???
done | awk -v series_name="${series_name}" -v lndir="${lndir}" '
 BEGIN { after_first=0 }
 (NR == FNR) { rem="we read the first file... so the episode list"
               episode[NR]=$0
 }

 ((NR != FNR) && ( after_first==0 )) { after_first=1; episode_number=0 }

 ((NR != FNR) && ( $0 ~ /..mp4|.mkv/ ) { 
   rem="NR>FNR, so we read the 2nd file, -, stdin..."
   rem="we also match .mp4 or .mkv, so we have a video file fullname as input"
   episode_number++
   fullfilename=$0; ext=fullfilename ; sub(".*[.]","",ext)
   destname = lndir "/" series_name " - " episode[episode_number] "." ext
   cmd="ln \"" fullfilename "\" \"" destname "\""
   printf("executing: %s\n",cmd)
   system(cmd); close(cmd)
 }
' "$episode_list" "-"  # first file is the episode_list file, then stdin
added match for video file names. and forgot to increment episode_number ...
Source Link
Olivier Dulac
  • 6.6k
  • 1
  • 26
  • 42
#!/usr/bin/env bash
_usage() {
  cat <<'EOF'
   this script needs at least those arguments:
     # $1=HardLinkDir, $2=series_name.txt # containing 1 line per episode name
     # $3 to $n : the directory, in order, with the *.mp4 and *.mkv in them, in order
   it will EMPTY the $1 directory, 
EOF
   for msg in "$@"; do printf "Erreur: %s\n" "$msg" ; done
   exit 1
}

if [ "$#" -lt 3 ]; then
   _usage "We need at least 3 args : HardLinkDir series_name.txt dirA ... "
fi
lndir="$1" ; 
episode_list="$2" ; series_name="${2/.txt/}" ; 
[ -d "$lndir" ] || _usage "arg1 : lndir=$lndir : is not a directory"
[ -f "$episode_list" ] || _usage "arg2 : episode_list=$episode_list : is not a file"
shift 2 # we "absorbed" the first 2 args : the rest are the dirs with the movie files
arg=2
for dir in "$@"; do 
  arg=$((arg + 1))
  [ -d "$dir" ] || _usage "arg${arg}: '$dir' : is not a directory."
done  

rm "${lndir:-__must_be_nonvoid__}"/*  # delete first the files in that dir, if any

for dir in "$@"; do
  ls "${dir}"/*.???
done | awk -v series_name="${series_name}" -v lndir="${lndir}" '
 BEGIN { after_first=0 }
 (NR == FNR) { rem="we read the first file... so the episode list"
               episode[NR]=$0
 }

 ((NR != FNR) && ( after_first==0 )) { after_first=1; episode_number=0 }

 ((NR != FNR) && ( $0 ~ /..mp4|.mkv/ ) { 
   rem="werem="NR>FNR, so we read the 2nd file, -, stdin..."
   rem="we also match .mp4 or .mkv, so stdin"we have a video file fullname as input"
   episode_number++
   fullfilename=$0; ext=fullfilename ; sub(".*[.]","",ext)
   destname = lndir "/" series_name " - " episode[episode_number] "." ext
   cmd="ln \"" fullfilename "\" \"" destname "\""
   printf("executing: %s\n",cmd)
   system(cmd); close(cmd)
 }
' "$episode_list" "-"  # first file is the episode_list file, then stdin
#!/usr/bin/env bash
_usage() {
  cat <<'EOF'
   this script needs at least those arguments:
     # $1=HardLinkDir, $2=series_name.txt # containing 1 line per episode name
     # $3 to $n : the directory, in order, with the *.mp4 and *.mkv in them, in order
   it will EMPTY the $1 directory, 
EOF
   for msg in "$@"; do printf "Erreur: %s\n" "$msg" ; done
   exit 1
}

if [ "$#" -lt 3 ]; then
   _usage "We need at least 3 args : HardLinkDir series_name.txt dirA ... "
fi
lndir="$1" ; 
episode_list="$2" ; series_name="${2/.txt/}" ; 
[ -d "$lndir" ] || _usage "arg1 : lndir=$lndir : is not a directory"
[ -f "$episode_list" ] || _usage "arg2 : episode_list=$episode_list : is not a file"
shift 2 # we "absorbed" the first 2 args : the rest are the dirs with the movie files
arg=2
for dir in "$@"; do 
  arg=$((arg + 1))
  [ -d "$dir" ] || _usage "arg${arg}: '$dir' : is not a directory."
done  

rm "${lndir:-__must_be_nonvoid__}"/*  # delete first the files in that dir, if any

for dir in "$@"; do
  ls "${dir}"/*.???
done | awk -v series_name="${series_name}" -v lndir="${lndir}" '
 BEGIN { after_first=0 }
 (NR == FNR) { rem="we read the first file... so the episode list"
               episode[NR]=$0
 }

 ((NR != FNR) && ( after_first==0 )) { after_first=1; episode_number=0 }

 (NR != FNR) { 
   rem="we read the 2nd file, -, so stdin"
   fullfilename=$0; ext=fullfilename ; sub(".*[.]","",ext)
   destname = lndir "/" series_name " - " episode[episode_number] "." ext
   cmd="ln \"" fullfilename "\" \"" destname "\""
   printf("executing: %s\n",cmd)
   system(cmd); close(cmd)
 }
' "$episode_list" "-"  # first file is the episode_list file, then stdin
#!/usr/bin/env bash
_usage() {
  cat <<'EOF'
   this script needs at least those arguments:
     # $1=HardLinkDir, $2=series_name.txt # containing 1 line per episode name
     # $3 to $n : the directory, in order, with the *.mp4 and *.mkv in them, in order
   it will EMPTY the $1 directory, 
EOF
   for msg in "$@"; do printf "Erreur: %s\n" "$msg" ; done
   exit 1
}

if [ "$#" -lt 3 ]; then
   _usage "We need at least 3 args : HardLinkDir series_name.txt dirA ... "
fi
lndir="$1" ; 
episode_list="$2" ; series_name="${2/.txt/}" ; 
[ -d "$lndir" ] || _usage "arg1 : lndir=$lndir : is not a directory"
[ -f "$episode_list" ] || _usage "arg2 : episode_list=$episode_list : is not a file"
shift 2 # we "absorbed" the first 2 args : the rest are the dirs with the movie files
arg=2
for dir in "$@"; do 
  arg=$((arg + 1))
  [ -d "$dir" ] || _usage "arg${arg}: '$dir' : is not a directory."
done  

rm "${lndir:-__must_be_nonvoid__}"/*  # delete first the files in that dir, if any

for dir in "$@"; do
  ls "${dir}"/*.???
done | awk -v series_name="${series_name}" -v lndir="${lndir}" '
 BEGIN { after_first=0 }
 (NR == FNR) { rem="we read the first file... so the episode list"
               episode[NR]=$0
 }

 ((NR != FNR) && ( after_first==0 )) { after_first=1; episode_number=0 }

 ((NR != FNR) && ( $0 ~ /..mp4|.mkv/ ) { 
   rem="NR>FNR, so we read the 2nd file, -, stdin..."
   rem="we also match .mp4 or .mkv, so we have a video file fullname as input"
   episode_number++
   fullfilename=$0; ext=fullfilename ; sub(".*[.]","",ext)
   destname = lndir "/" series_name " - " episode[episode_number] "." ext
   cmd="ln \"" fullfilename "\" \"" destname "\""
   printf("executing: %s\n",cmd)
   system(cmd); close(cmd)
 }
' "$episode_list" "-"  # first file is the episode_list file, then stdin
Source Link
Olivier Dulac
  • 6.6k
  • 1
  • 26
  • 42

basically : you need a script that takes N arguments, the first can be the resulting HardlinkDir, then a file with the episode names, and the rest can be dirA, dirB, dirC, etc.

to me the simplest is to 1) delete the content of the HardlinkDir dir, then for each files seen alphabetically in dirA, dirB dirC : ln that file. The titles could come from a separate file giving the name you want the Nth file to have ?

ie:

  • a file "series_name.txt" where you put all the episode names in order, 1 per line
  • a script to which you give the arguments: "$HardlinkDir" "$dirA" "$dirB" "$dirC" (...)

a simple solution with bash (calling a awk script to do the heavy lifting) is then:

#!/usr/bin/env bash
_usage() {
  cat <<'EOF'
   this script needs at least those arguments:
     # $1=HardLinkDir, $2=series_name.txt # containing 1 line per episode name
     # $3 to $n : the directory, in order, with the *.mp4 and *.mkv in them, in order
   it will EMPTY the $1 directory, 
EOF
   for msg in "$@"; do printf "Erreur: %s\n" "$msg" ; done
   exit 1
}

if [ "$#" -lt 3 ]; then
   _usage "We need at least 3 args : HardLinkDir series_name.txt dirA ... "
fi
lndir="$1" ; 
episode_list="$2" ; series_name="${2/.txt/}" ; 
[ -d "$lndir" ] || _usage "arg1 : lndir=$lndir : is not a directory"
[ -f "$episode_list" ] || _usage "arg2 : episode_list=$episode_list : is not a file"
shift 2 # we "absorbed" the first 2 args : the rest are the dirs with the movie files
arg=2
for dir in "$@"; do 
  arg=$((arg + 1))
  [ -d "$dir" ] || _usage "arg${arg}: '$dir' : is not a directory."
done  

rm "${lndir:-__must_be_nonvoid__}"/*  # delete first the files in that dir, if any

for dir in "$@"; do
  ls "${dir}"/*.???
done | awk -v series_name="${series_name}" -v lndir="${lndir}" '
 BEGIN { after_first=0 }
 (NR == FNR) { rem="we read the first file... so the episode list"
               episode[NR]=$0
 }

 ((NR != FNR) && ( after_first==0 )) { after_first=1; episode_number=0 }

 (NR != FNR) { 
   rem="we read the 2nd file, -, so stdin"
   fullfilename=$0; ext=fullfilename ; sub(".*[.]","",ext)
   destname = lndir "/" series_name " - " episode[episode_number] "." ext
   cmd="ln \"" fullfilename "\" \"" destname "\""
   printf("executing: %s\n",cmd)
   system(cmd); close(cmd)
 }
' "$episode_list" "-"  # first file is the episode_list file, then stdin

Please note: I just wrote this without testing it at all, as I can't right now test it... Maybe replace "rm" and "ln" above with: "echo rm" and "echo ln", respectively, to see what would be done... I also use only regular awk thinkgs ( hence the weird : ext=fullname; sub(....,ext) )