От сега предупреждавам – тази статия покрива много основни неща. Пиша я най-вече за себе си, за да не забравя как се прави, но ако успея да помогна на някого – добре сте дошли.
Както винаги – пиша за разрешаването на един единствен проблем. Не претендирам това да е най-лесни, най-елегантния или най-красивия начин. Сигурно има десет или 20 други начина с които да разрешите този проблем. Аз лично избрах този, защото мога да го имплементирам лесно.
Проблема:
Тъй като забравям изключително много, на повечето си телефони имам програмка за запис на разговори. Това е чудесно, но вече бях натрупал едно количество от около 250 файла със запис преди да разбера каква конвенция за името използва програмата, която използвах – [Име на контакта]_[Номер]_[Час]-[Минута]-[Секунда]_[Дата]-[Месец]-[Година].wav … нали се сещате каква бъркотия създава това, като се опитваш да търсиш разговор по дата … още по-лошо – когато знаеш ориентировъчен период … абе тъпотии. Тогава реших проблем частично, като свалих всички разговори които имах в една папка и промених конвенцията на [Номер]_[Час]-[Минута]-[Секунда]_[Дата]-[Месец]-[Година].wav … защо, ще попитате? Защото недогледах номерацията. Докато онзи ден не видях точно къде ми е грешката. Имам 1300 файла в две директории, които са непретърсваеми поради глупостта ми …
Решение:
Реших, че няма да е лошо да седна и да напиша малко скриптче което да преименува файловете, така, че да станат удобни за ровене, а именно [Номер]_[Час]-[Минута]-[Секунда]_[Дата]-[Месец]-[Година].wav да стане в YYYYMMDD-HHMMSS_нещо си. Речено сторено …
Тук ще ви предупредя, че смятам да разгледам всяка стъпка от създаването на скрипта … ако знаете как се прави – спрете да четете. Не ви трябва това. Ако все пак ви се иска – давайте на татък.
Стъпка 1 – Цъкълът!
Тъй като имаме да извършим неопределен брой операции, няма да е никак лошо да ги зациклим малко … за тези които не знаят (аз винаги го забравям) в Bash циклите са с for.
#/bin/bash for file in voix/*/*.wav dodone
Хубавото е че bash си взима съдържанието на директорията рекурсивно и го пуска като параметър на for. Или, преведено на човешки – докато имаш file в директорията прави следното.
Стъпка 2 – Директории и имена.
Тъй като $file връща цялото име на файла с който ще работим, а именно – voix/incoming(или outgoing)/нещоси, а аз искам и после да си ги разделя по папки, значи трябва да взема директорията за да я използвам.
#/bin/bashfor file in voix/*/*.wav dostate=`echo $file | cut -d/ -f2`nfile=`echo $file | cut -d/ -f3`done
На $state оказваме под директорията в която се намира файла с който работим (или раздели string-а на името на файла по всяка / и вземи втория възможен отговор. Това ни дава състоянието (дали е входящо или изходящо обаждане). После вземи третия параметър, защото това ти е името на самият файл, от което трябва да вземем информация за разговора, за да престрактурираме името – $nfile.
Стъпка 3 – част от името.
Основно името на файла, може да се разглежда като 4 основни части – [номер]_[време]_[дата].окончание, за това и ги присъединявам на 4 отделни променливи (ще видите, че по принцип се делят от _, но окончанието е разделено от останалото с . – тук на помощ идва последователното свързване на команди … но нека ви го покажа и да обясня после:
phn=`echo $nfile | cut -d_ -f1` rtime=`echo $nfile | cut -d_ -f2` rdate=`echo $nfile | cut -d_ -f3 | cut -d. -f1` rext=`echo $nfile | cut -d_ -f3 | cut -d. -f2`
Както и с $state по-горе, $phn (номер) и $rtime (време) се взимат като се раздели стринга на $nfile и взимаме съответно първата и втората част. $rdate и $rext обаче са различна картинка. Тъй като и за двете имаме нужда от част от третата част, за това и използваме отново cut, но този път с . и то само към третата част от низа …
Разбира се, след като имаме отделните части е време да ги разбием отново (датата и времето трябва да се подредят както трябва):
year=`echo $rdate | cut -d- -f3` month=`echo $rdate | cut -d- -f2` day=`echo $rdate | cut -d- -f1`hour=`echo $rtime | cut -d- -f1` minute=`echo $rtime | cut -d- -f2` second=`echo $rtime | cut -d- -f3`
Дори няма да обяснявам тук – вече съм обяснил всички части по-горе.
Стъпка 4 – Съществувам ли?
Тъй като искам да мога спокойно да местя директорията с преименуваните файлове, без да се притеснявам от загуби, а и не мога да променя voix, защото тази папка се синхронизира с телефона, нека проверим дали voix.ren (директория за преименуваните файлове) съществува, ако не – нека я създадем:
if [ ! -d "voix.ren" ]; then
mkdir voix.ren
fi
Добре де, но нали имаме и входящи и изходящи разговори? Значи е добре да създадем и тяхната структура (нали помните $state?):
if [ ! -d voix.ren/$state ]; then
mkdir voix.ren/$state
fi
А така … сега вече сме готови …
Стъпка 5 – новото име …
След като сме взели всички необходими променливи и сме подготвили структурата, време е да подредим новото име и да преименуваме файловте. Аз лично предпочитам да придам новото име на променлива и после нея на mv, но това си е избор на всеки.
newname="voix.ren/"$state"/"$year$month$day"-"$hour$minute$second"_"$phn"."$rextecho $file" -> "$newname mv $file $newname
За на края – целия код:
#/bin/bashfor file in voix/*/*.wav dostate=`echo $file | cut -d/ -f2`nfile=`echo $file | cut -d/ -f3`phn=`echo $nfile | cut -d_ -f1` rtime=`echo $nfile | cut -d_ -f2` rdate=`echo $nfile | cut -d_ -f3 | cut -d. -f1` rext=`echo $nfile | cut -d_ -f3 | cut -d. -f2`year=`echo $rdate | cut -d- -f3` month=`echo $rdate | cut -d- -f2` day=`echo $rdate | cut -d- -f1`hour=`echo $rtime | cut -d- -f1` minute=`echo $rtime | cut -d- -f2` second=`echo $rtime | cut -d- -f3`if [ ! -d "voix.ren" ]; then mkdir voix.ren fiif [ ! -d voix.ren/$state ]; then mkdir voix.ren/$state finewname="voix.ren/"$state"/"$year$month$day"-"$hour$minute$second"_"$phn"."$rextecho $file" -> "$newname mv $file $newname done
Вие разбира се може да не го направите така. Както казах – не е красиво. Но е функционално, а на мен ми трябва точно за това – да направи това, което искам от кода. Не искам да прави фокуси или да ми прави кафе. Искам да хване и да преименува едни файлове.
Надявам се съм ви бил полезен.
Ваш,
Lucifer