You are not logged in.

#1 2018-03-04 15:07:27

bheadmaster
Member
Registered: 2017-10-27
Posts: 43

Script for automatically updating cmus music library

Hey guys, I wrote a little script for automatically updating cmus music library, since doing it manually is a pain in the ass for any larger amount of music.
It defaults to /home/$USER/Music/ as the path for seeking music, but it can be easily changed.

#!/usr/bin/sh


# Directories where you want your music to be (put any others in new indices)
#
MUSIC_DIRS[0]="/home/$USER/Music/"
# MUSIC_DIRS[1]="/my/path/"


# File extensions you want to check for in a regex
#
FILE_EXTENSIONS_REGEX="^.*\.\(mp3\|ogg\|aiff\|flac\|wav\)$"


# Directory to the cmus library file
#
CMUS_LIB_DIR="/home/$USER/.config/cmus/lib.pl"

# Touch the cmus library file just in case it doesn't exist
#
touch "$CMUS_LIB_DIR"


# Append missing file paths to the .lib file
#
for dir_name in ${MUSIC_DIRS[*]}; do
	find "$dir_name" -iregex "$FILE_EXTENSIONS_REGEX" | \
	while read file_path; do
		if ! grep --fixed-strings --line-regexp --quiet \
			"$file_path" "$CMUS_LIB_DIR"; then

			echo "$file_path" >> "$CMUS_LIB_DIR"
		fi
	done
done

# Sort the file to get some consistency
#
sort "$CMUS_LIB_DIR" -o "$CMUS_LIB_DIR"

.............|
............/  GNU
........../
__---'''             o  LINUX

Offline

#2 2018-03-04 18:21:07

ayekat
Member
Registered: 2011-01-17
Posts: 1,589

Re: Script for automatically updating cmus music library

Hey, here's a little feedback on the code from my side:

shebang
It would be wise to use #!/bin/sh as shebang instead, to make the script usable on systems where /bin hasn't been merged with /usr/bin yet (e.g. Debian and most of its flavours). That being said, you use arrays (MUSIC_DIRS, for instance), so the shebang should really indicate a shell that supports arrays (e.g. #!/bin/bash or #!/usr/bin/zsh).
On a standard Arch Linux installation, this will not cause any issues, and I tend to be among the more pedantic people in the Arch Linux community when it comes to this particular issue, so for all I know, it may be OK to just ignore this advice.

home
I would replace "/home/$USER/Music/" simply by "$HOME/Music", or by ~/Music (it is not guaranteed that a user's home directory is really under /home).

XDG
~/.config is actually defined in the XDG base directory specification, and it is the default value if $XDG_CONFIG_HOME is not set. Instead of hardcoding that path (and annoying all people who use a different location), you could use something like this:

CMUS_LIB_DIR="${XDG_CONFIG_HOME:-$HOME/.config}/cmus/lib.pl"

the update
How do you actually detect files that have disappeared? Your code seems to only add files to the list, but not remove them. Also, since you have to scan through the list of files returned by the `find` command anyway, I think it would be a lot simpler to just overwrite the library file.
My approach would probably something like this:

: >"$CMUS_LIB_DIR"   # truncate the file
for dir_name in ${MUSIC_DIRS[*]}; do
    find "$dir_name" -iregex "$FILE_EXTENSIONS_REGEX" >> "$CMUS_LIB_DIR"
done

This is probably preferable because the library file is opened for writing once per iteration in that for-loop (instead of once for each scanned file), and there are no additional costs for invoking grep and opening the file for reading for each file.
... unless your disk is extremely slow for writing and extremely fast for reading, that is smile Actually, no: Most modern/journaled filesystems will relocate the file on disk anyway upon writing, so the amount of written data should actually be negligible in this case, if I'm not mistaken.

Last edited by ayekat (2018-03-04 19:08:21)


pkgshackscfgblag

Offline

#3 2018-03-04 19:54:23

bheadmaster
Member
Registered: 2017-10-27
Posts: 43

Re: Script for automatically updating cmus music library

Thank you for your feedback, I'm still a beginner when it comes to shell scripting, so your input is very appreciated.

Since most people only use one directory for storing music, I've removed the array thingy completely. Also, while rewriting the library would be an elegant solution, it would also wipe out all added music that was not from the music directory. So I figured I'd just remove every line that starts with "$MUSIC_DIR" and append all the found files.

This is the new result:

#!/bin/sh


# Directory containing the music to be read
MUSIC_DIR="$HOME/Music/"

# File extensions to check for
FILE_EXTENSIONS_REGEX="^.*\.\(mp3\|ogg\|aiff\|flac\|wav\)$"

# Directory to the cmus library file
CMUS_LIB_DIR="${XDG_CONFIG_HOME:-$HOME/.config}/cmus/lib.pl"


# Rewrite only the files from the $MUSIC_DIR directory
touch "$CMUS_LIB_DIR"
sed "s:^$MUSIC_DIR.*::gm;/^$/d" "$CMUS_LIB_DIR" --in-place
find "$MUSIC_DIR" -iregex "$FILE_EXTENSIONS_REGEX" >> "$CMUS_LIB_DIR"

# Sort the file for consistency
sort "$CMUS_LIB_DIR" -o "$CMUS_LIB_DIR"

Other solution would be to go line by line and check every single file for existence. But that sounds like a pain.

Last edited by bheadmaster (2018-03-04 19:55:34)


.............|
............/  GNU
........../
__---'''             o  LINUX

Offline

#4 2018-03-04 21:41:39

Trilby
Inspector Parrot
Registered: 2011-11-29
Posts: 29,515
Website

Re: Script for automatically updating cmus music library

While you got rid of the array, there was no need for it in the first place.  Find can process multiple paths at once:

MUSIC_DIRS="$HOME/Music/ /mnt/other/music"
...
find $MUSIC_DIRS -iregex ...

Also note that "--in-place" is only for gnu sed.  While POSIX doesn't have an in place option, every implementation I'm aware of does allow an -i option, but *only* with the suffix supplied (which gnu sed considers optional), so for a much more portable version consider the following:

sed -i '' "s:..."

(that's a single quoted empty string after the -i)


"UNIX is simple and coherent..." - Dennis Ritchie, "GNU's Not UNIX" -  Richard Stallman

Offline

#5 2018-03-04 22:13:44

bheadmaster
Member
Registered: 2017-10-27
Posts: 43

Re: Script for automatically updating cmus music library

Find can process multiple paths at once:

I didn't think of that, but it could still make problems if the directory were to contain a space in the name, which is a pretty common thing in music directory trees. I can't think of a way that can be curcumvented, except with eval, and something like this:

[...]
MUSIC_DIRS="'/first path/with spaces/' '/second path/with more spaces/'"
eval $(echo "find $MUSIC_DIRS")

Which seems like a really bad hack.

Also, it seems that GNU sed requires the suffix right next to the -i, without space:

sed -i'' ...

While FreeBSD implementation requires a space between them. *sigh*

I'll see if I can do without using it at all. I hate inconsistency.


.............|
............/  GNU
........../
__---'''             o  LINUX

Offline

#6 2018-03-04 22:41:16

Alad
Wiki Admin/IRC Op
From: Bagelstan
Registered: 2014-05-04
Posts: 2,411
Website

Re: Script for automatically updating cmus music library

printf '%s\n' "$path1" "$path2" | xargs -I{} find {} ...

http://pubs.opengroup.org/onlinepubs/00 … xargs.html

Last edited by Alad (2018-03-04 22:41:40)


Mods are just community members who have the occasionally necessary option to move threads around and edit posts. -- Trilby

Offline

#7 2018-03-04 22:48:21

Trilby
Inspector Parrot
Registered: 2011-11-29
Posts: 29,515
Website

Re: Script for automatically updating cmus music library

bheadmaster wrote:

but it could still make problems if the directory were to contain a space in the name...

set -- $HOME/Music /mnt/other/music
find "$@" -iregex ...

POSIX does not have arrays.  It has one array smile

Last edited by Trilby (2018-03-04 22:49:05)


"UNIX is simple and coherent..." - Dennis Ritchie, "GNU's Not UNIX" -  Richard Stallman

Offline

#8 2018-03-05 10:53:26

ayekat
Member
Registered: 2011-01-17
Posts: 1,589

Re: Script for automatically updating cmus music library

About the -i option for sed: the following should be POSIX-conform (at least I'm using it in all my scripts):

printf '%s/foo/bar/g\nwq\n' | ex -s "$CMUS_LIB_DIR"

(note that the regex syntax in ex is slightly different from/limited compared to sed)


pkgshackscfgblag

Offline

Board footer

Powered by FluxBB