Scheduled Maintenance: We are aware of an issue with Google, AOL, and Yahoo services as email providers which are blocking new registrations. We are trying to fix the issue and we have several internal and external support tickets in process to resolve the issue. Please see: viewtopic.php?t=158230

 

 

 

[Bash] Question about brace expansion as an argument

Programming languages, Coding, Executables, Package Creation, and Scripting.
Post Reply
Message
Author
mrjpaxton
Posts: 18
Joined: 2021-07-09 02:35
Been thanked: 2 times

[Bash] Question about brace expansion as an argument

#1 Post by mrjpaxton »

Hey everyone,

I'm trying to figure something out that relates to the Bash shell and my Bash script. So I have a script that uses ffprobe to process data for a bunch of audio files and print out stuff I can parse to check audio parameters and quality.

As a lazy way to run the script, I've run it like this:

Code: Select all

ffprobe-audio-quality-check.sh *.{flac,mp3,wav}
The thing is, I don't know what audio files and formats I'll be working with, so this is more of a lazy catch-all way of doing it, rather than doing a regular "*" glob. Because regular globs can match album art, playlists, etc... in the same folder.

In the beginning of my script, I have also set a default argument to use, like this:

Code: Select all

if [ $# -lt 1 ]; then
    set -- *.{flac,mp3,wav}
fi
Then the main loop begins, for example, like this:

Code: Select all

for f in "$@"; do
    # Print the filename
    printf "%s\n" "$f"
    ...
    <do stuff>
done
But my problem is when the files are all *.mp3, and there is no *.flac or *.wav, I get an error that says "*.flac: No such file or directory", because in the expansion, *.flac is expanded first before *.mp3. And depending on how the script functions, it may or may not run or work normally after that, and then *.wav is expanded, and returns the same type of error for that.

What I would like to do is prevent the errors somehow--or maybe look at a better way of doing this. I know there is a possibility of maybe using the "find" command instead of a "for" loop, because it can process a list of files better. But could I do this and still pass in arguments such as a glob or list of files like "*.{flac,mp3,wav}" without any errors?

Whatever I'm doing, it's not working out. Like the expansion and glob stuff in Bash is just still confusing to me on how it works in 100% detail. Any help, or even some ideas, is much appreciated.

mrjpaxton
Posts: 18
Joined: 2021-07-09 02:35
Been thanked: 2 times

Re: [Bash] Question about brace expansion as an argument

#2 Post by mrjpaxton »

Okay, I am pretty dumb... as how most programmers and scripters feel.

All I really needed was a check inside the beginning of the loop:

Code: Select all

#!/usr/bin/env bash

# If there are no arguments specified, set default arguments
if [ $# -lt 1 ]; then
    set -- *.{flac,mp3,wav}
fi

for f in "$@"; do
    # Skip files or patterns that do not exist
    if [ ! -r "$f" ]; then
        >&2 printf "Error: \"%s\" does not exist or read access not given. Skipping...\n" "$f"
        continue
    fi
    
    # Print the filename
    printf "%s\n" "$f"

    ... <do stuff>

done

User avatar
sunrat
Administrator
Administrator
Posts: 6511
Joined: 2006-08-29 09:12
Location: Melbourne, Australia
Has thanked: 119 times
Been thanked: 489 times

Re: [Bash] Question about brace expansion as an argument

#3 Post by sunrat »

Could you post the rest of your script? Using ffprobe to query audio file parameters looks quite useful.
“ computer users can be divided into 2 categories:
Those who have lost data
...and those who have not lost data YET ”
Remember to BACKUP!

CwF
Global Moderator
Global Moderator
Posts: 2719
Joined: 2018-06-20 15:16
Location: Colorado
Has thanked: 41 times
Been thanked: 201 times

Re: [Bash] Question about brace expansion as an argument

#4 Post by CwF »

Wow, how did I miss ffprobe!? I will be looking into this one, there are many 'probers' I use for my tcl/tk interface multi-widget. The output is a little noisy but there is useful info there...

User avatar
sunrat
Administrator
Administrator
Posts: 6511
Joined: 2006-08-29 09:12
Location: Melbourne, Australia
Has thanked: 119 times
Been thanked: 489 times

Re: [Bash] Question about brace expansion as an argument

#5 Post by sunrat »

CwF wrote: 2023-11-28 16:34The output is a little noisy but there is useful info there...
You can cut out most of the noise with

Code: Select all

ffprobe -hide_banner <file>
I always knew that! I looked it up last night. :lol:
Be worth making an alias to include -hide_banner as the default behaviour.

For supported files I have always used soxi. It doesn't support mp3 natively though.
“ computer users can be divided into 2 categories:
Those who have lost data
...and those who have not lost data YET ”
Remember to BACKUP!

mrjpaxton
Posts: 18
Joined: 2021-07-09 02:35
Been thanked: 2 times

Re: [Bash] Question about brace expansion as an argument

#6 Post by mrjpaxton »

sunrat wrote: 2023-11-28 07:35 Could you post the rest of your script? Using ffprobe to query audio file parameters looks quite useful.
Yeah, sure. I can still polish it up, but it works fine for my use cases.

Code: Select all

#!/usr/bin/env bash

# If there are no arguments specified, set default arguments
if [ $# -lt 1 ]; then
    set -- *.{flac,mp3,ogg,wav}
fi

for f in "$@"; do
    # Skip files or patterns that do not exist
    if [ ! -r "$f" ]; then
        >&2 printf "Error: \"%s\" does not exist or read access not given. Skipping...\n" "$f"
        continue
    fi

    # Print the filename
    printf "%s\n" "$f"

    # Uncomment to show all available stream and format (container) tags
    #ffprobe -v warning -hide_banner -show_streams -show_format "$f"

    line=()
    while IFS= read -r; do
        line+=("$REPLY")
    done < <(\
        ffprobe -v warning -hide_banner -select_streams a \
        -show_entries "stream=codec_name,sample_fmt,sample_rate,channels,channel_layout,bit_rate,bits_per_raw_sample:format=bit_rate" \
        -of default=nk=1:nw=1 "$f" \
    )

    # Print the output
    printf "%s, %s Hz, %s (%s ch), %s" "${line[0]}" "${line[2]}" "${line[4]}" "${line[3]}" "${line[1]}"
    [ "${line[6]}" != "N/A" ] && printf " (%s-bit)" "${line[6]}"

    if   [ "${line[5]}" != "N/A" ]; then
        printf "\nStream bitrate: %u kb/s" "$((line[5]/1000))"
    elif [ "${line[7]}" != "N/A" ]; then
        printf "\nBitrate (avg.): %u kb/s" "$((line[7]/1000))"
    fi

    printf "\n\n";

    # DEBUG: Show the line array
    #declare -p line

    # The old way (for reference)
    #ffprobe -v info -select_streams a "$f"
done
Though usually just checking bitrate is not enough. I then usually open up downloaded FLACs in Audacity and enable the spectrogram for the track to make sure they are truly FLAC, and not just converted from MP3 hopefully. Though there is a bug where if you scroll around too fast when generating the spectrogram, Audacity will crash. I hope they fix that at some point. Then I check to make sure there is no frequency cut-off below around 14-16 KHz, or clipping, or strange noise signals, because some things in audio are easier to see than to hear.

Another lightweight option is to use Spek instead.

User avatar
sunrat
Administrator
Administrator
Posts: 6511
Joined: 2006-08-29 09:12
Location: Melbourne, Australia
Has thanked: 119 times
Been thanked: 489 times

Re: [Bash] Question about brace expansion as an argument

#7 Post by sunrat »

@mrjpaxton Thanks! Works great for a single directory of files.
Here's a challenge - make it work recursively for multiple directories. I tried a couple of things like feeding it from find, but ultimately failed.
“ computer users can be divided into 2 categories:
Those who have lost data
...and those who have not lost data YET ”
Remember to BACKUP!

CwF
Global Moderator
Global Moderator
Posts: 2719
Joined: 2018-06-20 15:16
Location: Colorado
Has thanked: 41 times
Been thanked: 201 times

Re: [Bash] Question about brace expansion as an argument

#8 Post by CwF »

mrjpaxton wrote: 2023-11-29 12:54 Another lightweight option is to use Spek instead.
Another addition for my widget I hadn't ran across yet! It's incredibly fast too.

In my herder.tk gui for cli stuff stuffed into gui ease, I have not yet finished all that can be done with audio files. Part of that issue is simply deciding...The handling of video files is done but audio has a longer history of variation and I haven't devised a single routine for all situations. After that, if ever, I will attempt directory or even full tree handling and it could be a mess.

Post Reply