Дилан,
Ваша домашняя работа дает мне идею сделать что-то и с моей музыкальной библиотекой, и я вижу, чем вы пытаетесь сделать свою домашнюю работу в одиночку, поэтому вот некоторые комментарии - как сделать musicsort
команда:)
Основная сила программирования оболочки заключается в его способности конвейеризовать и разбивать работу на маленькие части, в то время как эти маленькие части могут легко играть вместе.
, следовательно,
Этоне очень хорошая идея менять порядок столбцов.См. Например ls -l
.Неважно, по каким параметрам вы хотите отсортировать вывод (например, ls -lt = по времени или ls -ltr = по времени, но в обратном порядке), порядок столбцов остается неизменным.Таким образом, вы можете легко передать вывод команды ls другой команде, не беспокоясь о порядке столбцов.И если вам действительно нужно изменить это, вот уже инструменты, которые могут сделать это эффективно.
Мое первое предложение - не меняйте порядок выходных столбцов, сортируйте только по ним.
Второй - строка заголовка.Печать ставить только тогда, когда действительно этого захочешь.(например, для нормального вывода), потому что, когда вам позже понадобится конвейеризовать вывод вашей новой команды musicsort
, заголовки вызовут много проблем.Итак,
мое второе предложение - печатать заголовок только на основе аргумента команды.
Когда мы разбираем вашу проблему, мы получаем:
- нужен некоторый аргумент командной строкиобработка
- необходимо установить некоторые значения по умолчанию, если здесь нет аргументов
- нужно найти музыкальные файлы в вашей музыкальной директории
- нужно отсортировать их по критериям
- нужно распечататьони - в отсортированном порядке
Пропуск 1,2 на данный момент.
Поиск файлов в вашем музыкальном каталоге очень прост.
find "$musicdir" -type f -print
распечатает все файлы рекурсивно,Конечно, здесь могут быть некоторые изображения обложек и текст txt, поэтому нужно их отфильтровать, например, с помощью
find "$musicdir" -type f -print | egrep -i '\.(mp3|aif*|m4p|wav|flac)$'
у нас есть все ваши музыкальные файлы.Хорошо разделенный символом / в следующем порядке:
/path/to/musicdir/genre/artist/album/track.suffix
. Для вывода нам нужно удалить / path / to / musicdir /.Это легко.Вот еще один способ, например sed
.
sed "s:^$musicdir/::;s:\.[^/][^/]*$::"
Вышеуказанная команда выполняет две вещи: 1.) удаляет путь $ musicdir из вашего списка файлов и тоже удаляет любой .suffix.(например .mp3 .flac и т. д.).Результат:
genre/artist/album/track
Хорошая строка, четко разделенная - такая сортируемая.Для сортировки у нас есть команда sort
.sort
может сортировать по любому полю и, возможно, сказать ему, что такое разделитель полей.
Например,
sort -df -t/ -k2,2
отсортирует ввод, разделенный знаком '/', вторым полем (исполнитель).Для -df смотрите man sort
.
и, наконец, нам нужно прочитать уже отсортированный список файлов в переменные и распечатать.(здесь, конечно, есть и другой способ).Для этого в bash есть команда read
.И мы должны сказать bash, каков его временный разделитель полей (IFS), так:
IFS=/; read genre artist album track
и поскольку у нас больше строк на входе, мы должны делать это в цикле, тогда как у нас есть строки на входе.
Окончательный сценарий находится здесь:
musicdir="."
FORMAT="%-20s%-35s%-35s%-35s\n"
sortby=2 #for this example - artist
find "$musicdir" -type f -print |\
egrep -i '\.(aif*|mp3|flac|m4a|wav)$' |\
sed "s:^$musicdir/::;s:\.[^/][^/]*$::" |\
sort -t/ -k$sortby,$sortby | (
IFS=/; while read genre artist album track
do
printf "$FORMAT" $genre $artist $album $track
done)
Как видите, весь поиск, сортировка, печать выполняется в несколько строк.(части 3, 4, 5).
Для финала нужно сделать некоторую обработку аргументов.Я написал один, это не на 100% нормально, но работает.
Последний скрипт, который может обрабатывать некоторые аргументы, устанавливать значения по умолчанию и выполнять основные функции, может выглядеть следующим образом: (ofc, здесь возможновыполнить оптимизацию zilion, например, объединить egrep и sed только в один sed и т. д.)
#!/bin/bash
#argument handling - not 100% correct, but working...
while getopts "hHgaltd:" arg
do
case "$arg" in
g) sortby=1;;
a) sortby=2;;
l) sortby=3;;
t) sortby=4;;
d) musicdir=$OPTARG;;
H) header=y;;
h|?) echo "Usage: $0 [-d music_dir] [-g|-a|-l|-t] [-H]";
echo ' -d music_dir = path to your music directory (default ".")'
echo ' -g|-a|-l|-t = for sorting by Genre/Artist/aLbum/Track (default "-a")'
echo ' -H print header (default no)'
exit 1;;
esac
done
#defaults
sortby=${sortby:=2};
musicdir=${musicdir:=.}
FORMAT="%-20s%-35s%-35s%-35s\n"
#header only if want one
if [[ $header == "y" ]]
then
printf "$FORMAT" genre artist album track
printf -v line '%*s' 125; echo ${line// /-}
fi
#the main part - search, sort, read into variables, print
find "$musicdir" -type f -print |\
egrep -i '\.(aif*|mp3|flac|m4a|wav)$' |\
sed "s:^$musicdir/::;s:\.[^/][^/]*$::" |\
sort -t/ -k$sortby,$sortby | (
IFS=/; while read genre artist album track
do
printf "$FORMAT" $genre $artist $album $track
done)
, например,
$ musicsort -t -H -d .
будет производить вывод, отсортированный подорожки, заголовок печати и музыка находятся в текущем каталоге
genre artist album track
-----------------------------------------------------------------------------------------------------------------------------
Electronic Squarepusher Hard Normal Daddy Cooper's World
Electronic Squarepusher Go Plastic Go! Spastic
Electronic Squarepusher Go Plastic Greenways Trajectory
Electronic Squarepusher Feed Me Weird Things Kodack
Electronic Squarepusher Go Plastic My Red Hot Car
Electronic Squarepusher Feed Me Weird Things North Circular
Electronic Squarepusher Hard Normal Daddy Papalon
Hip-Hop OutKast Stankonia Toilet Tisha
Electronic Squarepusher Feed Me Weird Things Tundra
Electronic Squarepusher Hard Normal Daddy Vic Acid
Как видите, 3/4 строки - это обработка аргументов и другие вещи.Основная часть выполняется в несколько строк.
Если вам действительно нужно изменить порядок столбцов, это легко сделать, добавив несколько строк форматирования ...