samplesort - converts audiosample-directories into symbolically linked trees sorted on tags (kick/hihat/etc)
#!/bin/sh | |
# | |
# this will build a database using the 'mlocate' package (see debian/ubuntu etc) | |
# make sure to set 'export LOCATE_PATH="/path/to/mlocate.db"' when using 'locate' | |
renice +19 -p $$ >/dev/null 2>&1 | |
ionice -c2 -n7 -p $$ >/dev/null 2>&1 | |
/usr/bin/updatedb --output /path/to/mlocate.db --local-path -U /path/to/your/samples |
#!/bin/bash | |
# | |
# Copyright 2012, Leon van Kammen (Coder of Salvation), All rights reserved. | |
# | |
# Redistribution and use in source and binary forms, with or without modification, are | |
# permitted provided that the following conditions are met: | |
# | |
# 1. Redistributions of source code must retain the above copyright notice, this list of | |
# conditions and the following disclaimer. | |
# | |
# 2. Redistributions in binary form must reproduce the above copyright notice, this list | |
# of conditions and the following disclaimer in the documentation and/or other materials | |
# provided with the distribution. | |
# | |
# THIS SOFTWARE IS PROVIDED BY Coder of Salvation ``AS IS'' AND ANY EXPRESS OR IMPLIED | |
# WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND | |
# FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> OR | |
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR | |
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON | |
# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | |
# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF | |
# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
# | |
# The views and conclusions contained in the software and documentation are those of the | |
# authors and should not be interpreted as representing official policies, either expressed | |
# or implied, of Coder of Salvation | |
# | |
me=$(basename "$0"); cur_dir=""; cur_file=""; dry=0; autolink=0; initialized=0 | |
requirements="sed grep printf cut sort echo" | |
filetypes="(\.wav$|\.mp3$|\.ogg$|\.flac$|\.aiff$|\.iff$)" | |
declare -A tags | |
tags["kick"]="kick|bassdrum" | |
tags["loop_kick"]="kick.*loop|bassdrum.*loop" | |
tags["hihat"]="hihat|hats" | |
tags["clap"]="clap" | |
tags["snare"]="snare" | |
tags["ride"]="ride" | |
tags["crash"]="crash|cymbal" | |
tags["percussion_acoustic"]="clave|tom|bongo|conga|shaker|mallet|wood|whistle" | |
tags["percussion_mixed"]="percussion|perc" | |
tags["loop"]="loop" | |
tags["loop_perc"]="perc.*loop|loop.*perc" | |
tags["loop_beat"]="drum.*loop|loop.*drum" | |
tags["loop_beat_top"]="loop.*top" | |
tags["loop_bass"]="bass.*loop|loop.*bass" | |
tags["loop_guitar"]="guitar.*loop|loop.*guitar" | |
tags["instrument"]="instrument" | |
tags["keyboard"]="keyboard|keys" | |
tags["breakbeat"]="breakbeat" | |
tags["guitar"]="guitar" | |
tags["drumkit"]="drumkit" | |
tags["groove"]="groove|groovy" | |
tags["minimal"]="minimal|glitch" | |
tags["scratch"]="scratch|turntabl" | |
tags["hiphop"]="scratch|turntabl|hiphop|vinyl" | |
tags["reverse"]="reverse" | |
tags["jazz"]="jazz|swing" | |
tags["brass"]="brass|tuba" | |
tags["rhodes"]="wurly|wurlitz|rhodes" | |
tags["strings"]="string|pizzi" | |
tags["oneshots"]="oneshot|shot" | |
tags["pads"]="pad" | |
tags["synth"]="lead|synth" | |
tags["bass"]="bass$|bass |bassl" | |
tags["vocal"]="vocal|vox|female|male|human" | |
tags["fx"]="fx" | |
tags["sweep"]="woosh|sweep" | |
tags["funkdisco"]="disco|funk|filter" | |
tags["robotvocoder"]="vocoder|robot" | |
tags["environment"]="environment|movienoise" | |
alltags="" | |
initialize(){ | |
rootdir="$1" | |
outputdir="$2" | |
symlinkprefix="$3" | |
[[ "$initialized" = 1 ]] && return; # prevent second init | |
[[ ! -d "$outputdir" ]] && echo "[!] $outputdir does not exist" | |
[[ ! -d "$rootdir" ]] && echo "[!] $rootdir does not exist" | |
for tag in ${!tags[@]}; do | |
alltags="$tag|$alltags" | |
done | |
alltags="$(echo "$alltags"| sed 's/|$//g')" | |
initialized=1 | |
} | |
checkrequirements(){ | |
for req in $requirements; do | |
hash "$req" 2>&- | |
if [ $? == 1 ]; then echo "sorry..you need to install '$req'"; exit; fi | |
done; | |
} | |
usage(){ | |
printf "Usage: \n" | |
grep "^[^_].\+(){$" $0 | while read line; do | |
local cmd=$(echo "$line" | sed "s/(){//g") | |
local info=$(grep -C0 -A0 -B1 "$cmd(){" $0 | sed "N;s/\n.*//g" ) | |
printf " $me %-7s %-20s\n" "$cmd" "$info" | grep "#" | sed "s/#//g" | |
done; echo ""; | |
printf "type '$me --manual' to see the manual + examples\n\n" | |
return 0 | |
} | |
manual(){ | |
if [ "$1" != "--manual" ]; then return 0; fi | |
hash pod2man 2>&- | |
if [ $? == 1 ]; then echo "sorry..you need to install 'pod2man' (perl)"; exit; fi | |
SCRIPT=`readlink -f $0` | |
echo "(please wait..)" | |
pod2man $SCRIPT > /tmp/sortsamples.1 | |
clear | |
if [ -f /tmp/sortsamples.1 ]; then man /tmp/sortsamples.1; rm /tmp/sortsamples.1; fi | |
exit 0 | |
} | |
# <string> #(will tell if it can be tagged) | |
matchtag(){ | |
dir=$(basename "$1") | |
outputdir="$2" | |
symlinkprefix="$3" | |
initialize "$dir" "$outputdir" "$symlinkprefix" | |
nop=$(echo "$dir" | grep -iE "($alltags)" ) | |
[[ $? = 1 ]] && return 1; | |
for tag in ${!tags[@]}; do | |
if echo "$(basename "$dir")" | grep -iE "(${tags[$tag]})" > /dev/null; then | |
echo "...tagged with '$tag'!" | |
[[ "$autolink" == 1 ]] && _createlink "$1" "$tag" "$outputdir" "$symlinkprefix" | |
fi | |
done | |
} | |
_createlink(){ | |
dir="$1" | |
dirname=$(basename "$1") | |
tag="$2" | |
outputdir="$3" | |
symlinkprefix="$4" | |
[[ ! -d "$outputdir/$tag" ]] && mkdir "$outputdir/$tag" 2> /dev/null | |
index="$(ls "$outputdir/$tag" | wc -l)" | |
if [[ "$dry" == 1 ]]; then | |
echo "ln -s '$symlinkprefix$dir' '$outputdir/$tag/$index-$dirname" | |
else | |
ln -s "$symlinkprefix$dir" "$outputdir/$tag/$index-$dirname" | |
fi | |
} | |
#<inputdir> <outputdir> <symlink-prefix> # (see what will be done) | |
sort-dry(){ | |
dry=1 | |
sort "$1" "$2" "$3" "4" | |
} | |
# <inputdir> <outputdir> <symlink-prefix> # (do it!) | |
sort(){ | |
rootdir="$1" | |
outputdir="$2" | |
symlinkprefix="$3" | |
autolink="1" | |
initialize "$rootdir" "$outputdir" "$symlinkprefix" | |
echo "[x] preparing.. *drumrolls*" | |
find "$rootdir" -type d | while read dir; do | |
tput el; printf "\r[x] scanning %s" "$dir" | |
matchtag "$dir" "$outputdir" "$symlinkprefix" | |
find "$dir" -type f | grep -iE "$filetypes" | while read file; do | |
matchtag "$file" "$outputdir" "$symlinkprefix" | |
done | |
done | |
} | |
manual "$1" && test $# -lt 2 && checkrequirements && usage && exit 65 | |
"$@" | |
exit 0 | |
: <<=cut | |
=head1 NAME | |
sortsamples - a cmdline utility to easify sample organizing without organizing :) | |
=head1 SYNOPSIS | |
This utility solves the problem of having many samplecd/samplelibrary-directories with each having | |
kick,hihat,snare-etc folders. | |
=head1 DESCRIPTION | |
With many sampledirectories, you ll be slapped around many directories hunting | |
for kicks/hihats etc. This utility creates symbolic links to directories which are similar. | |
This way, you can have all your kick directories next to eachothers and so on. | |
=head1 WHY | |
External Sampleorganizing utilities can also become a pain in the ass, | |
because usually your DAW also has a samplebrowser in it. It would be nice to have structure at the | |
source: the filesystem. | |
This is a crazy effort to combine similar folders and categorize automatically :) | |
=head1 EXAMPLES | |
Examples: | |
$ ls -la | |
total 31152 | |
drwxrwxrwx 1 root root 4096 Jul 25 17:52 . | |
drwxrwxrwx 1 root root 36864 Jul 10 10:15 .. | |
drwxrwxrwx 1 root root 4096 Jul 24 22:40 samplecd | |
-rwxr-xr-x 1 sqz users 6669 Jul 25 17:52 sortsamples | |
$ mkdir sorted-by-tag | |
$ sudo ./sortsamples sort-dry samplecd sorted-by-tag ../../ | |
[x] preparing.. *drumrolls* | |
[x] scanning samplecd/Blutonium hardstyle vol 2/BASSDRUM...tagged with 'kick'! | |
[x] scanning samplecd/Blutonium hardstyle vol 2/BASSLINE...tagged with 'bass'! | |
[x] scanning samplecd/Blutonium hardstyle vol 2/FX...tagged with 'fx'! | |
^C (interrupted by CTRL-c, because it looks good..lets make it so) | |
$ sudo ./sortsamples sort samplecd sorted-by-tag ../../ | |
[x] preparing.. *drumrolls* | |
[x] scanning samplecd/Blutonium hardstyle vol 2/BASSDRUM...tagged with 'kick'! | |
[x] scanning samplecd/Blutonium hardstyle vol 2/BASSLINE...tagged with 'bass'! | |
[x] scanning samplecd/Blutonium hardstyle vol 2/FX...tagged with 'fx'! | |
.. and so on! | |
=head1 SEE ALSO | |
L<https://gist.github.com/3097565>, L<https://gist.github.com/1916306> | |
=head1 LICENSE | |
BSD License (so everybody can enjoy it) | |
=head1 AUTHOR | |
B<C>oder B<O>f B<S>alvation | LEON DU STAR | info@leon.vankammen.eu | info@leondustar.nl | |
=cut | |
"$@" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment