LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Linux - Software (https://www.linuxquestions.org/questions/linux-software-2/)
-   -   album songs play out of sequence (https://www.linuxquestions.org/questions/linux-software-2/album-songs-play-out-of-sequence-940147/)

Yuhan 04-16-2012 10:17 PM

album songs play out of sequence
 
I have downloaded a few albums and when I play them back through mplayer, they play songs out of sequence. For some albums the official song sequence is important and I don't like hearing them played back out of order. Is there anything that can be done to correct this? I have been using a terminal with the command:
mplayer ~/Music/folder/album title *.mp3.
Then the album begins with track 10! Why would this be? I welcome any advice on how to get the tracks to play in order. I should add that the numbered play list is perfectly in order, but the songs won't play that way. I will appreciate any input on this--thanks in advance.

Tinkster 04-16-2012 11:42 PM

ASCII sort-order?

Code:

$ ls -1
10abc
1abc
2cde
3vfr
4bgt
5nhy
6muj
7gyu
8asf
9ikhj

$ ls -1
01_abc
02_cde
03_vfr
04_bgt
05_nhy
06_muj
07_gyu
08_asf
09_ikhj
10_abc

The trick is to use sensible names ;}



Cheers,
Tink

Yuhan 04-17-2012 08:13 AM

Tink, this is not quite what I mean...I don't think. The songs are actually listed in correct numerical order--they appear in the folder in the proper numeric sequence. But the song sequence begins with song #10 goes through #14 and then starts 1-9. It's weird. My sense is this is the order in which the songs were downloaded and that's why they play back in that order, regardless of the numbers in front of them. Looking at your chart, I'm wondering: Does it matter whether you have the numbered sequence as "01, 02, 03, etc." as opposed to "1,2,3...etc."? As I said, it doesn't proceed "10, 1, 2, 3...etc." It goes from "10, 11, 12, 13, 14 and then begins with "1, 2, 3...up to 9" and then ends. If I do need to change this numbering sequence so the computer understands in which order to play back the songs, where do I make these changes? Thanks!

David the H. 04-17-2012 09:08 AM

That certainly looks like ascii sort order to me. The system doesn't treat the digits as numbers, but only as individual characters; so it starts by sorting the first character in the names (all the ones first, then all the twos, etc), then sorts the second character, etc.

But whether or not the sort order is ascii, whenever you use globbing you're going to get the files in the order the system thinks they should be in, and it's probably not going to be numerical order. Try using "printf '%s\n' *.mp3" to see exactly what file order the pattern produces.

In any case, padding the numbers with zeros will likely give you the playback order you want. Another option may be to pipe the list through sort -n, but getting the output to work correctly might be tricky if there are spaces in the filenames.

I wrote a script a while back that will pad numbers in filenames. Give it a try.

Code:

#!/bin/bash

# Pads numbers in file names if found.
# See help message for more.

# Set the environment
shopt -s extglob
IFS=""

BCYAN="${BCYAN:-\e[1;36m}"    #Define some color codes, for prettified output.
#BGREEN="${BGREEN:-\e[1;32m}"  #Use environment defaults if they exist.
#BRED="${BRED:-\e[1;31m}"
#BBLUE="${BBLUE:-\e[1;34m}"
#BMAGENTA="${BMAGENTA:-\e[1;35m}"
RESET="${RESET:-\e[0m}"

#set default padding level
pad=2


# Set up the help dialog
help(){
        local -a help
        help+=( ''                                                                                                                                                                )
        help+=( '\tA quick script to zero-pad files that contain numbers.'                                                                        )
        help+=( '\tIt will only pad the first number string it finds in the name, and ignores files without numbers.'        )
        help+=( ''                                                                                                                                                                )
        help+=( "\tUsage: \t${BCYAN}${0##*/} [-n <num>] <files>${RESET}"                                                                                )
        help+=( "\t\t${BCYAN}${0##*/} -h${RESET}"                                                                                                                )
        help+=( ''                                                                                                                                                                )
        help+=( '\tUse -n to specify the number of digits to pad, from 1-9.  Defaults to '"$pad"' if not used.'                )
        help+=( '\tIf no files are given, it processes the current directory.'                                                                )
        help+=( ''                                                                                                                                                                )
        help+=( '\t-h prints this help message'                                                                                                                        )
        help+=( ''                                                                                                                                                                )

        local IFS=$'\n'
        echo -e "${help[*]}"
}


# Process input options
# If "-h" print help & exit.
# If "-n" test for valid inputs and set "pad" variable
# Ignore anything else
while getopts ":hn:" opt; do

    case "$opt" in

          h) help >&2
            exit "2"
          ;;

          n)        if [[ "$OPTARG" =~ [^[:digit:]] ]] || (( "10#$OPTARG" < 1 )) || (( "10#$OPTARG" > 9 )); then
                                echo
                                echo -e "${BCYAN}invalid option: [$OPTARG].${RESET}" >&2
                                echo -e "${BCYAN}-n must be an integer from 1 to 9${RESET}" >&2
                                echo -e "${BCYAN}Falling back to the default of $pad${RESET}"
                                echo
                        else
                                pad="$(( 10#$OPTARG ))"
                        fi
          ;;

          \?) echo -e "${BCYAN}Invalid option: [-$OPTARG].  Ignoring.${RESET}" >&2
          ;;
    esac
done

shift $(( OPTIND - 1 )) ; OPTIND=1

# Now test for files.
# If nothing given, set input parameters to files in current directory.
if [[ -z "$*" ]]; then
        set -- ./*
fi

# Process files in input parameters
re='([^[0-9]*)([0-9]+)(.*)'

for file ; do

        # Ignore files without digits
        [[ "$file" != *[0-9]* ]] && continue

        # Split filename into prefix-digits-suffix
        [[ "$file" =~ $re ]]

        # Pad digits to desired width
        printf -v numpad "%0*d" "$pad" "${BASH_REMATCH[2]##*(0)}"

        # Add old and new filenames to arrays for final processing
        oldfile+=( "$file" )
        newfile+=( "${BASH_REMATCH[1]}${numpad}${BASH_REMATCH[3]}" )

done

# If there are any files to rename, ask to confirm the operation.
# And rename if confirmed.
if [[ -n "${oldfile[*]}" ]]; then

        echo
        echo -e "${BCYAN}Rename the following files?${RESET}"
        echo
        for i in "${!oldfile[@]}" ; do
                echo -e "${oldfile[i]/#$PWD/.}\t-->\t${newfile[i]/#$PWD/.}"
        done
        echo

        read -p "(y/n): "

        echo

        case "${REPLY,,}" in

                y*)          for i in "${!oldfile[@]}" ; do
                                        mv -n "${oldfile[i]}" "${newfile[i]}"
                                done
                                echo
                                ;;

                *)                echo -e "${BCYAN}Aborting.${RESET}"
                                echo
                                exit 1
                                ;;
        esac

# Otherwise just exit.
else
        echo
        echo -e "${BCYAN}No files to rename.${RESET}" >&2
        echo -e "${BCYAN}Exiting.${RESET}" >&2
        echo
        exit 1

fi

exit 0


Yuhan 04-17-2012 09:19 AM

David, your explanation was excellent and professional...but way too technical for me! I admire your script writing abilities and wish I had a portion of your knowledge. As it turns out, just inserting the "0" before the single digits did the trick! In the future, what's the way to accomplish this changing of numbers sequence in the terminal? I had to go into the music folder on my desktop and then "rename" the 1-9 songs individually. Is there a more expedient way you can accomplish this within the terminal, without having to rewrite the name of the whole song and the number? Thanks for this. Very helpful! Incidentally, if you have any suggestions for how a Linux novice can become more proficient with scripting, or just knowing how to use basic commands in the terminal, I would welcome your suggestions! Again, thanks Trink and David!

David the H. 04-17-2012 09:28 AM

Quote:

Originally Posted by Yuhan (Post 4655094)
Is there a more expedient way you can accomplish this within the terminal, without having to rewrite the name of the whole song and the number?

Um, yeah. With the script I just posted.

Copy the text into a text file and name it to something like "padnumbers.sh". Make it executable with "chmod -x padnumbers.sh". then just run "/path/to/padnumbers.sh *.mp3". It zero-pads files with numbers to two digits by default, and it will prompt you for confirmation.

As for learning scripting, study and practice, just like anything else. 10 years ago I was a rank beginner too. And now there are better resources available.

Here are a few useful bash scripting references:
http://mywiki.wooledge.org/BashGuide
http://mywiki.wooledge.org/BashFAQ
http://mywiki.wooledge.org/BashPitfalls
http://www.linuxcommand.org/index.php
http://tldp.org/LDP/Bash-Beginners-G...tml/index.html
http://www.tldp.org/LDP/abs/html/index.html
http://www.gnu.org/software/bash/manual/bashref.html
http://wiki.bash-hackers.org/start
http://ss64.com/bash/

I particularly recommend the BashGuide and the linuxcommand pages for beginners.

kitgerrits 04-17-2012 04:03 PM

Alternatively, you can instruct your MP3 ripping software to pad the track#.

Tinkster 04-17-2012 07:37 PM

Quote:

Originally Posted by kitgerrits (Post 4655456)
Alternatively, you can instruct your MP3 ripping software to pad the track#.

While this is true it's of little help if he downloaded
the songs, as he said..

273 04-17-2012 07:44 PM

Quote:

Originally Posted by Tinkster (Post 4655573)
While this is true it's of little help if he downloaded
the songs, as he said..

He could ask the artist to name the files more conveniently.
In future he will also know to name the tracks more conveniently.

cascade9 04-18-2012 06:33 AM

Quote:

Originally Posted by Yuhan (Post 4655094)
I had to go into the music folder on my desktop and then "rename" the 1-9 songs individually. Is there a more expedient way you can accomplish this within the terminal, without having to rewrite the name of the whole song and the number?

You can also use easytag to do the renaming from a GUI if you prefer.

Select the files you want to rename. Scanner-> Process Fields, change to 'Rename File and Directory'. I use 'n%.t%' (tracknumber.tracktitle) myself, that would give you filenames like '01.trackone'. I dont bother with artist, year, etc. in the fielname as that is in the path with my system (so the full path would be something like /Music/S/Severed.Heads/1989.Rotund.For.Success/01.All.Saints.Day.flac)

That will only work if your tags are filled. You can normally get the tag info from CDDB, and if that doesnt work you can fill the tag fileds from the file naming. E.g. if the file names are '1abc' like in Tinksters example, you should be able to get track number and song title.

Yuhan 04-18-2012 07:27 AM

Thanks one and all for the complete info! Duly appreciated! When inserting a script, does it have to be identified as such or does Linux simply recognize a script as distinct from a command? I wanted to be sure how to include David's script above. Last night a friend sent me another script he said might work.

#!/bin/sh
mplayer `ls ~/$1/*.mp3 |sort -df`

Does this seem it would do the job? I know little about scripts other than I'm impressed with people's ability to write them! Without diverting too much from the topic at hand, both this script and David's above were written for Bash editors. I've heard some people sing the praises of KornShell as an editor. What determines the use for one editor over another?

Tinkster 04-18-2012 02:13 PM

Quote:

Originally Posted by Yuhan (Post 4656080)
Thanks one and all for the complete info! Duly appreciated! When inserting a script, does it have to be identified as such or does Linux simply recognize a script as distinct from a command? I wanted to be sure how to include David's script above. Last night a friend sent me another script he said might work.

#!/bin/sh
mplayer `ls ~/$1/*.mp3 |sort -df`

Does this seem it would do the job? I know little about scripts other than I'm impressed with people's ability to write them! Without diverting too much from the topic at hand, both this script and David's above were written for Bash editors. I've heard some people sing the praises of KornShell as an editor. What determines the use for one editor over another?

I doubt it would make a change to the way they're played back; sort -df,
apart for comparing upper & lower-case letters as equal, sorts in the
same was as shell globbing, so 10, 11, 12 would still show before 2.


Cheers,
Tink

David the H. 04-19-2012 08:02 AM

The shell treats the first word on the command line as the name of the command to execute. If a file matching that name is found in one of your PATH directories (use "echo $PATH" to see), and is executable, then the shell will launch it. If the command is not in your path, then you have to supply it with the full (relative or absolute) pathname (e.g. "./scriptname"), to tell the shell where it is.


As for that new script, you'll notice I already mentioned piping the output through sort, and the problems you'll likely encounter if there are any spaces in the filenames. As written, the shell will be unable to differentiate between whitespace inside the names and the whitespace separating them. You'd have to use a more complex loop and null separators to do it safely. Nor should it be using ls to supply sort with the file list, for pretty much the same reason.

Finally, as Tinkster mentioned, it really needs to be using the -n (numeric sorting) option rather than -d (dictionary sorting).


It is possible to write a safe script, but it's really much better in the long run just to ensure that your files are properly padded.

David the H. 04-19-2012 08:20 AM

As for your choice of shell, in the end it comes down to personal choice. They all have individual features, syntax, and quirks to differentiate them. ksh and bash seem to have a pretty good mutual feedback thing going, where new features appearing in one eventually make it into the other, although it appears that korn is the one that usually introduces new ideas first. At an off-guess, I'd say about 80% of their shell grammar is the same.

bash is the default on Linux, of course, and therefore the one that most people know the best. Most of the users here have little experience with ksh or other shells, meaning you're less likely to get less helpful advice from us.

If you really want a feature-rich shell, you might check out zsh, which is an attempt to combine the best (in the developer's opinions) features of all the other shells. Or if you want to go the other way, stick with posix-defined syntax only, and use dash (I don't recommend this, BTW), or try the new simplified, non-posix fish.

Whatever you do, though, you probably should not choose any of the c-shell variants.

Yuhan 04-20-2012 06:40 AM

Thanks for all the above. Really, I'm not savvy enough to distinguish between the merits/demerits of the various shells. I've just heard from some, apparently accurately, that ksh is a few notches ahead of bash and those who know it well (ksh) are in demand. It is perhaps that slight edge over bash that David speaks of. Is learning the language of the shell different from learning the commands of Linux generally? What is the relation of the particular shell to the basic Linux program? I still use Ubuntu so I'm just feeling my way to the command line.


All times are GMT -5. The time now is 02:25 PM.