Post

Some bash stuff

.bashrc

The .bashrc file is a script that executes on each log in. Most of these snippets are functions, though for most one-liners without much input, it might be best to make an alias

length () {
    ffprobe "$1" 2>&1  | grep -oP "Duration: \K[^,]+" | awk -F: '{printf "%d hours, %d minutes, %d seconds\n", $1, $2, $3}'
}

For this one, by running length filename.mkv, it will execute ffprobe on the first argument (which is represented as $1 in bash), redirects stderr to stdout (because ffprobe writes info to stderr for some reason). Then, it pipes the output to grep, where the -o flag tells it to isolate our ffprobe output to just the section that would say “Duration: 05:23:21,”.

Now we have a little bit of what we want, but it doesn’t look very nice. We can do some more filtering with grep, using the -P flag to make it use Perl-compatible regex. In this case, [^,]+ essentially means everything before the comma, and \K (more info here) tells it to discard everything before those numbers, leaving us with “05:23:21”.

Now that we have an easily parsable string, we can pipe it again to awk, where -F: tells it to use “:” as a field seperator. From there, you use the printf function in awk, where %d tells it to expect an integer, and $1, $2 and $3 represent our first, second and third numbers and \n simply makes it print a new line.

This should finally get you “5 hours, 23 minutes, 21 seconds”.

explicit() {
    for filename in *"(Explicit)"*; do
       new_name=$(echo $filename | sed 's/\ (Explicit)//')
       mv "$filename" "$new_name"
    done
}

When you run explicit, this takes a file with a name that contains “(Explicit)”, assigns the new_name variable to the output of echo $filename | sed 's/\ (Explicit)//', which replaces the “(Explicit)” with nothing and then renames the the old $filename to the $new_name variable, then loops for each filename with the the string we defined in the for loop

extract () {
   if [ -f $1 ] ; then
       case $1 in
           *.tar.bz2)   tar xvjf "$1"           ;;
           *.tar.gz)    tar xvzf "$1"           ;;
           *.tar.zst)   tar -I zstd -xvf "$1"   ;;
           *.tar.xz)    tar xf "$1"             ;;
           *.tar)       tar xvf "$1"            ;;
           *.tbz2)      tar xvjf "$1"           ;;
           *.tgz)       tar xvzf "$1"           ;;
           *.bz2)       bunzip2 "$1"            ;;
           *.rar)       unrar x "$1"            ;;
           *.gz)        gunzip "$1"             ;;
           *.zip)       unzip "$1"              ;;
           *.Z)         uncompress "$1"         ;;
           *.7z)        7z x "$1"               ;;
           *.xz)        unxz "$1"               ;;
           *.zst)       unzstd "$1"             ;;
           *)           echo "Unsupported file type" ;;
       esac
   else
       echo "'$1' is not a valid file"
   fi
 }

First, it uses if [ -f $1 ] to check if the argument exists and is valid. If it isn’t, it will print “whatever.invalid is not a valid file”. Then, it uses a case statement to determine what it should do, depending on the file type. If the file ends in .tar.gz, it would run tar xvzf "{your first argument}". It then uses esac (case spelled backwards) to close the case statement and fi to close the first if statement.

optimize() {
    local quality=80
    while [ "$#" -gt 0 ]; do
        case "$1" in
            -q)
                local quality="$2"
                shift 2
                ;;
            *)
                break
                ;;
        esac
    done
    echo "Quality: $quality"
    for file in "$@"; do
        if [[ $file != *.webp ]]; then
            basename=${file%.*}
            cwebp -m 6 -q $quality "$file" -o "$basename.webp"
            rm "$file"
        else
            mv "$file" "$file.old"
            cwebp -m 6 -q $quality "$file.old" -o "$file"
            rm "$file.old"
        fi
    done
}

This one has a bit more logic. It defines quality as 80 using a local variable, so $quality will only work within this function, then while number of arguments (represented as $# in bash) is greater than 0, it checks for the -q flag. If it’s present, it will re-assign our quality varible to the value passed in the -q flag, and then use shift $2 to ignore -q and it’s value in the next portion. If there is no -q flag, it usesbreakto exit the while loop. It prints the quality, which will be 80 by default, or whatever was specified in -q. Then, for each argument, it does a check to see if the file already ends in .webp. If it doesn’t, it assigns the basename variable to everything that comes before the final . in the file name. Then, it runs cwebp with the quality option we defined, setting the output to $basename.webp and removing the old file. If the file already ends with .webp, it adds .old to the end of it’s name, compresses it with cwebp, and then removed the old file.