Page 1 of 2 12 LastLast
Results 1 to 10 of 11

Thread: Understanding a sed line in a bash script.

  1. #1
    Join Date
    Jul 2011
    Location
    /Europe/Netherlands
    Beans
    378
    Distro
    Kubuntu 22.04 Jammy Jellyfish

    Understanding a sed line in a bash script.

    I found a script to generate moodbars for Amarok http://wiki.ubuntuusers.de/Moodbar#Unter-Amarok.

    The complete script:
    Code:
    #!/bin/bash
    control_c()        # Den Vorgang abbrechen, wenn der Nutzer Strg+c drückt
    {
     echo $1 > lastreadsong
     echo "Exiting..."
     exit
    }
    if [ -e lastreadsong ]; then
      read filetodelete < lastreadsong
      rm "$filetodelete" lastreadsong
    fi
    find . -type f -regextype posix-awk -iregex '.*\.(mp3|ogg|flac|wma)' | while read i
    do
      trap 'control_c "$OUTF"' SIGINT
      TEMP="${i%.*}.mood"
      OUTF=`echo "$TEMP" | sed 's#\(.*\)/\([^,]*\)#\1/.\2#'`
      if [ ! -e "$OUTF" ]; then
        moodbar -o "$OUTF" "$i"
      fi
    done
    I understand what the script does but I don't see what the sed line does exactly. This is the part I'm interested in:
    Code:
      TEMP="${i%.*}.mood"
      OUTF=`echo "$TEMP" | sed 's#\(.*\)/\([^,]*\)#\1/.\2#'`
    How does it work? All that seems necessary is to add a "." before the filename, other than that TEMP seems to contain the right value.

  2. #2
    Join Date
    Jul 2007
    Location
    Poland
    Beans
    4,499
    Distro
    Ubuntu 14.04 Trusty Tahr

    Re: Understanding a sed line in a bash script.

    TEMP line strips shortest possible rightside (%) '.'+anything (.*) - read: extension - and adds .mood
    OUTF line pipes $TEMP value to sed which splits the whole path in 2 parts with the last /, effectively cutting it to path (\1) and filename (\2) parts. Then it glues them back with /. which effectively means the filename got prefixed with .
    with -r parameter the picture is clearer
    sed -r 's#(.*)/([^,]*)#\1/.\2#'

    Why the filename part is matched by not-colon any number of times [^,]* - no idea.

    Code:
    $ i=/some/path/file.mp3
    $ TEMP="${i%.*}.mood"
    $ echo "$TEMP"
    /some/path/file.mood
    $ OUTF=$( echo "$TEMP" | sed -r 's#(.*)/([^,]*)#\1/.\2#' )
    $ echo "$OUTF"
    /some/path/.file.mood
    the same behavior in pure bash using trimming shortest rightside (%) /* pattern and longest leftside (##) */ pattern. More efficient than creating separate sed process for each file
    Code:
    $ OUTF=${TEMP%/*}/.${TEMP##*/}
    $ echo "$OUTF"
    /some/path/.file.mood
    Last edited by Vaphell; August 18th, 2013 at 05:15 PM.
    if your question is answered, mark the thread as [SOLVED]. Thx.
    To post code or command output, use [code] tags.
    Check your bash script here // BashFAQ // BashPitfalls

  3. #3
    Join Date
    Aug 2011
    Location
    47°9′S 126°43W
    Beans
    2,172
    Distro
    Ubuntu 16.04 Xenial Xerus

    Re: Understanding a sed line in a bash script.

    Would not that be simpler (or at least more readable)?
    Code:
    OUTF=$(dirname $i)/.$(basename $i .mp3).mood

  4. #4
    Join Date
    Jul 2011
    Location
    /Europe/Netherlands
    Beans
    378
    Distro
    Kubuntu 22.04 Jammy Jellyfish

    Re: Understanding a sed line in a bash script.

    Thanks Vaphell and ofnuts! Well especially Vaphell here for the extensive explanation

    Your solutions are a lot friendlier on the eyes let's say regular expressions are not my strongest point.

    @ofnuts
    Your solution looks elegant but the problem is that my collection contains music with different extensions. it could be .mp3 but also .ogg .wma (one pesky folder) or .flac

  5. #5
    Join Date
    Oct 2010
    Location
    Above ground...(for now)
    Beans
    761

    Re: Understanding a sed line in a bash script.

    Quote Originally Posted by Vaphell View Post
    ...Why the filename part is matched by not-colon any number of times [^,]* - no idea...
    Well, not to be a nitpicker, but to correctly name the character for what it is, because I'll be referring to it later: it's a comma, not a colon.
    The negated character class: [^,]* matches any non-comma character zero or more times. The author may know that none of his filename parts contain commas. So this allows him to match the entire filename part.
    It might be argued that he could accomplish the same match by using: .*
    However, the dot metacharacter does not actually match any single character. It matches any single character EXCEPT for newline characters. In essence, the dot metacharacter in Unix regex is short for: [^\n]
    So, assuming the author knows that none of his filename parts contain commas, and he wants his match to include newline characters, then the negated character class: [^,]* works for him whereas: .* does not.
    (Ref.: http://www.regular-expressions.info/dot.html)

    Now everybody can sleep tonight
    Last edited by Crusty Old Fart; August 19th, 2013 at 03:22 AM.
    Suffering from severe chronic female supervision deficiency syndrome resulting in
    an increasing intolerance of adolescent scatological effluence and PMS induced nefarious diatribe.
    How to: Mark your thread as: [SOLVED]

  6. #6
    Join Date
    Jul 2007
    Location
    Poland
    Beans
    4,499
    Distro
    Ubuntu 14.04 Trusty Tahr

    Re: Understanding a sed line in a bash script.

    my bad, i always have trouble recalling english names of ,:;
    if your question is answered, mark the thread as [SOLVED]. Thx.
    To post code or command output, use [code] tags.
    Check your bash script here // BashFAQ // BashPitfalls

  7. #7
    Join Date
    Jul 2011
    Location
    /Europe/Netherlands
    Beans
    378
    Distro
    Kubuntu 22.04 Jammy Jellyfish

    Re: Understanding a sed line in a bash script.

    Thanks again I'll mark this as solved as I have successfully executed the script with Vaphells code instead of the sed line.

    Code:
    musicdir="$HOME/Music/"
    find $musicdir -type f -regextype posix-awk -iregex '.*\.(mp3|ogg|flac|wma|m4a)' | while read i
    do
        TEMP="${i%.*}.mood"
        OUTF=${TEMP%/*}/.${TEMP##*/}    
        if [ ! -e "$OUTF" ];
        then
            moodbar -o "$OUTF" "$i"
        fi    
    done
    Last edited by Erik1984; August 19th, 2013 at 04:16 PM. Reason: Slight code improvement.

  8. #8
    Join Date
    Jul 2007
    Location
    Poland
    Beans
    4,499
    Distro
    Ubuntu 14.04 Trusty Tahr

    Re: Understanding a sed line in a bash script.

    home/$USER is less rocksolid than simple $HOME (you don't have to have your homedir in /home, root cerainly doesn't) but $HOME will always point to the right place)
    if your question is answered, mark the thread as [SOLVED]. Thx.
    To post code or command output, use [code] tags.
    Check your bash script here // BashFAQ // BashPitfalls

  9. #9
    Join Date
    Jul 2011
    Location
    /Europe/Netherlands
    Beans
    378
    Distro
    Kubuntu 22.04 Jammy Jellyfish

    Re: Understanding a sed line in a bash script.

    Thanks, changed it. I put $USER there to 'censor' my username which is in the script on my machine. $HOME seems a better choice to distribute the script for common use.

  10. #10
    Join Date
    Aug 2011
    Location
    47°9′S 126°43W
    Beans
    2,172
    Distro
    Ubuntu 16.04 Xenial Xerus

    Re: Understanding a sed line in a bash script.

    Quote Originally Posted by Euroman View Post
    Thanks Vaphell and ofnuts! Well especially Vaphell here for the extensive explanation

    Your solutions are a lot friendlier on the eyes let's say regular expressions are not my strongest point.

    @ofnuts
    Your solution looks elegant but the problem is that my collection contains music with different extensions. it could be .mp3 but also .ogg .wma (one pesky folder) or .flac
    Hmmm Then technically nothing says you won't get "foo.mp3" and "foo.ogg" in the same folder, so the extension shouldn't be removed (.foo.mp3.mood).

Page 1 of 2 12 LastLast

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •