Learning to Script in Linux

Hello,

I'm trying to branch out and learn Linux, but my comfort zone is PowerShell. I figure the best way to learn it is to do it so I moved my Plex Media Server to Ubuntu Server.

What I'm trying to do is build a script that searches a directory and all subdirectories for files with the .ts extension, then sends them to handbrakecli to get converted, then deletes the .ts file because its huge. Here's what I've got so far. It's a mix of PowerShell and what I've gleened/stolen from around the internet. I've commented the end of each line that isn't bash, but I'm sure you guys will be able to tell.

#SRC=./SOURCE_FOLDER/
    #DEST=./DESTINATION_FOLDER/
    DEST_EXT=mp4
    HANDBRAKE_CLI=/Applications/HandBrakeCLI
    PRESET="Roku 720p30 Surround"

$NeedToConvert = Get-ChildItem -Path '/mnt/raid' -Recurse -include "*.ts" #PowerShell
foreach($file in $NeedToConvert){ #PowerShell
    $Location = $file.DirectoryName #PowerShell
    $FileName = $File.name.substring(
    SRC=$Location #mix
    DEST=$file.name.substing(0,(file.name.length)-3) #mix
    DEST=$Location #mix
    $HANDBRAKE_CLI -i $SRC/$FILE -o $DEST.$DEST_EXT --preset="$PRESET"
    if(Test-Path -Path PathToNewFile){ #PowerShell
        $file.delete() #PowerShell
    } #PowerShell
 } #PowerShell

Any help or pointers in the right direction would be awesome!

This should get you started:

SRC=./SOURCE_FOLDER/
DEST=./DESTINATION_FOLDER/
DEST_EXT=mp4
HANDBRAKE_CLI=/Applications/HandBrakeCLI
PRESET="Roku 720p30 Surround"


find /mnt/raid -iname "*.ts" -print | while read filepath
do
    LOCATION=${filepath%/*}  # Delete everything in $filepath from last slash to end and store in LOCATION
    FILENAME=${filepath##*/} # Delete everything in $filepath from front to last slash and store in FILENAME
    SRC=${LOCATION}
    DEST=${FILENAME%.*}      # Delete everything in $FILENAME from last dot to end and store in DEST   

    $HANDBRAKE_CLI -i "$SRC/$FILENAME" -o "$SRC/${DEST}.${DEST_EXT}" --preset="$PRESET"
    if [ -s "$SRC/${DEST}.${DEST_EXT}" ]    # File exists and has size greater than zero
    then
        rm "$filepath"
    fi
done
2 Likes

@Chubler_XL Thanks! I don't have the time right now to dive all the way in but just playing with the find command and digging through its manual...thanks so much. I'll let you know.

---------- Post updated at 08:57 PM ---------- Previous update was at 05:39 PM ----------

So the find command prints out all of the ts files, and the script works when I run it, but it stops after the first encode. I'm not sure why. Is it something to do with handbrakecli coming back and basically saying "hey i'm done" causing the script to then think that it too is done?
Heres the output for the end:

Muxing: this may take awhile...[00:44:05] mux: track 0, 133307 frames, 1434924901 bytes, 2520.47 kbps, fifo 2048
 [00:44:05] mux: track 1, 213492 frames, 93191479 bytes, 163.69 kbps, fifo 4096
[00:44:05] mux: track 2, 142325 frames, 218611200 bytes, 383.99 kbps, fifo 2048
[00:44:05] libhb: work result = 0

Encode done!

HandBrake has exited.
 rhys@odin:~$

and here's what I ran. a couple small changes, one to correct a mistake in what I originally posted, and a change to the path to limit the number of tracks it would find.

#!/bin/bash

SRC=./SOURCE_FOLDER/
DEST=./DESTINATION_FOLDER/
DEST_EXT=mp4
#HANDBRAKE_CLI=/Applications/HandBrakeCLI
PRESET="Roku 720p30 Surround"


find '/mnt/raid/Kids Movies' -iname "*.ts" -print | while read filepath
do
    LOCATION=${filepath%/*}  # Delete everything in $filepath from last slash to end and store in LOCATION
    FILENAME=${filepath##*/} # Delete everything in $filepath from front to last slash and store in FILENAME
    SRC=${LOCATION}
    DEST=${FILENAME%.*}      # Delete everything in $FILENAME from last dot to end and store in DEST

    HandBrakeCLI -i "$SRC/$FILENAME" -o "$SRC/${DEST}.${DEST_EXT}" --preset="$PRESET"
    if [ -s "$SRC/${DEST}.${DEST_EXT}" ]    # File exists and has size greater than zero
    then
        rm "$filepath"
    fi
done
 

It should have moved on to the second movie in the folder with the matching .ts extension, but it stopped after the first one.

I'm assuming that the done is the closer of the while loop and that it should hit done and move back to the while (so long as there is another input).

Thanks for any help.

Nothing in that loop ought to make it quit, so maybe it only found one movie for some reason. Run that find statement by itself and see how many files it finds.

Hello again,

Its been a minute since i've been here, but i finally figured it out. Here is the end result:

#!/bin/bash

#build an array of the results of find
array=()
while IFS=  read -r -d $'\0'; do
    array+=("$REPLY")
done < <(find '/mnt/raid/media' -iname "*.ts" -print0)

#go through the results
arrayLength=${#array[@]}
for (( i=0; i<$arrayLength; i++ ))
do
        filepath=${array[$i]}
        echo "${filepath}" >> '/home/rhys/converted_files.log'
    LOCATION=${filepath%/*}  # Delete everything in $filepath from last slash to end and store in LOCATION
    FILENAME=${filepath##*/} # Delete everything in $filepath from front to last slash and store in FILENAME
    SRC=${LOCATION}
    DEST=${FILENAME%.*}      # Delete everything in $FILENAME from last dot to end and store in DEST
        #convert movie
        HandBrakeCLI -i "$SRC/$FILENAME" -o "$SRC/${DEST}.mp4" --preset="Roku 720p30 Surround" -s "1,2,3,4,5,6"
        ExitCode=$?
        if [ $ExitCode -ne 0 ]
        then
                echo "failed. removing faulty file" >> 'home/rhys/converted_files.log'
                rm "$filepath" #it didn't work. Delete the faulty file
        fi

        if [ -s "$SRC/${DEST}.${DEST_EXT}" ]    # File exists and has size greater than zero
        then
        rm "$filepath" #it worked and the old ts file can be removed
    fi
    sleep 2 #cuz even CPUs deserve a short break
done

something about the while loop wasn't working. I had it echo the filepath before it began and that showed me that although running the find by itself as suggested showed all the files, the second time through the loop it returned an empty string instead of the next item in the list.
That's when I decided to put it in an array and loop through it. Thanks for the help, especially that first bit with the comments showing what each line did. Helped me crack the code so to speak :smiley:

I'm sure you guys will see me around.

The symptom "while read loop stops after one cycle" is typical for a conmand that reads from stdin, sucking from the input that is for the read command.
Maybe HandBrakeCLI is such a command? Then it helps to redirect its input

</dev/null HandBrakeCLI ...

or

HandBrakeCLI ... < /dev/null
2 Likes