Multi-rename

Trebao bih preimenovati veći broj datoteka, avi i srt da budem precizan:

Enterprise 1x03.avi Enterprise 1x03.Fight or flight.srt Enterprise 1x04.avi Enterprise 1x04.Strange new world.srt Enterprise 1x05.avi Enterprise 1x05.Unexpected.srt
Znači, trebalo bi preimenovati avi fajl tako da naziv bude identičan odgovarajućem srt fajlu.

Upomoć :wink:

Probaj

rename *1x03.srt *1x03.avi *1x03.srt itd…

PS

Tek sam ustao :smiley:

Nisam vican BASH scriptingu (sigurno ce ti Adis il neko dobacit neko rjesenje), al evo ekvivalent u PHPu (kad koristis Command Line Interface, php-cli paket):

[code]#!/usr/bin/php

<?php // dobijes listing svih srt fajlova $dir=opendir("./"); while($file=readdir($dir)){ if($file != '.' && $file!='..' && preg_match("/(.*)\.srt$/i",$file) ){ $files[] = $file; } } closedir($dir); // dobijes listing svih avi fajlova $dir=opendir("./"); while($file=readdir($dir)){ if($file != '.' && $file!='..' && preg_match("/(.*)\.avi$/i",$file) ){ $avi[] = $file; } } // renameujes na osnovu onoga do prve tacke foreach($avi as $avifile){ foreach($files as $srtfile){ $tacka_u_avi=strpos($avifile,"."); $tacka_u_srt=strpos($srtfile,"."); $avi_c=substr($avifile,0,$tacka_u_avi); $srt_c=substr($avifile,0,$tacka_u_srt); if($avi_c==$srt_c){ $novo_ime=substr($srtfile,0,-4).".avi"; rename($avi_c,$novo_ime); } } } ?>[/code]

Moze to i mnogo jednostavnije al zavisi sta ti treba (a poprilicno sam siguran da u bashu moze u par linija).

A ovo je mozda zanimljivije: http://www.cyberciti.biz/tips/renaming-multiple-files-at-a-shell-prompt.html

Pošto srt datoteke imaju potpunije nazive:

for f in *.srt; do base=${f%.*} prefix=${base%.*} mv "$prefix.avi" "$base.avi" done

  1. Ogulimo “srt” ekstenziju,
  2. nađemo zajednički prefix za srt i avi (“Enterprise 1x0N”)
  3. rename
  4. Profit!!!

Što se tiče tog PHP koda, osim što se treba eksplicitno otvoriti direktorij, i u PHP-u je trivijalno rješenje.
Još kad bi se umjesto regularnih izraza koristio fnmatch() ili ne daj Bože substr() :wink:

[quote]Some people, when confronted with a problem, think “I know, I’ll use regular expressions.” Now they have two problems.
–Jamie Zawinski, in comp.lang.emacs[/quote]

instaliraj krename, pa naklikaj ko covjek :wink:

Daleko najbolje rjesenje :smiley:

Sumnjam, u apsolutnom smislu te riječi, najbolje rješenje jeste ono kad čovjek nauči bash/python/perl pa može sam rješavati ovakve svakodnevne “probleme”. “Give a man a fish and you feed him for a day. Teach a man to fish and you feed him for a lifetime.”

Dopuštam mogućnost da je nekada i krename prihvatljivo rješenje, za male vrijednosti t :wink:

[quote=adis]Pošto srt datoteke imaju potpunije nazive:

for f in *.srt; do base=${f%.*} prefix=${base%.*} mv "$prefix.avi" "$base.avi" done

  1. Ogulimo “srt” ekstenziju,
  2. nađemo zajednički prefix za srt i avi (“Enterprise 1x0N”)
  3. rename
  4. Profit!!![/quote]
    To je upravo ono što mi je trebalo!

PS: Koliko ja znam, ovo je nemoguće uraditi pomoću krename-a.

Protestiram - nisi naveo RUBY ! :slight_smile:

[quote=adis]for f in *.srt; do base=${f%.*} prefix=${base%.*} mv "$prefix.avi" "$base.avi" done
[/quote]
Jedini problem ovog rješenja je što pretpostavlja da nakon tačke kojom se završava baza nema više tačaka do ekstenzije (.srt). Možda korištenje regexa pravi probleme (nekome), ali takođe omogućuje programeru da se izrazi prirodnim jezikom što sprječava greške kao što je ova. Kada znaš jezik regexa, možeš fino reći kompjuteru “daj mi sve od prve tačke do .srt, zatim na to nakalemi .avi” i on fakat to i uradi :slight_smile:

. - tačka - treba nam backslash pošto sama tačka ima posebno značenje

[^.] - ne tačka - negacija se formira pomoću uglastih zagrada i znaka ^

[^.]* - gomila znakova koji nisu tačka

[^.]*? - dodajemo upitnik kako matching ne bi bio “greedy” tj. umjesto da obuhvati što je više moguće želimo da obuhvati što je manje moguće. Da ne komplikujem sada, ako nisi siguran uvijek stavi upitnik nakon zvjezdice :slight_smile: Označimo ovaj regex sa $1

.*? - bilo koja gomila znakova. Tačka bez backslasha znači “bilo koji znak”. - $2

([^.]?).(.?) - $1 pa tačka pa $2, pri čemu smo $1 i $2 stavili u zagrade radi kasnije zamjene

([^.]?).(.?).srt - dodajemo .srt kako bi $2 obuhvatao sve do ovog teksta

Po ukusu dodati ^ na početak a $ na kraj :slight_smile:

Sada pišemo kod:

[code]#/usr/bin/perl

opendir(DIR,"."); # Otvaramo direktorij
foreach (readdir(DIR)) { # Čitamo sve fajlove iz direktorija
if (/^([^.]?).(.?).srt$/) { # Ako ime odgovara našem šablonu…
rename ("$1.avi","$1.$2.avi"); # preimenuj odgovarajući avi
}
}
closedir(DIR); # kraaaaaaaaaaaaj :)[/code]
Poenta ove vježbe je bila: nekad ćeš se susresti sa fajlovima čija su imena razdvojena zarezom ili razmakom ili sa " - "…

Jesi probao uopšte?

[code]${var%Pattern}, ${var%%Pattern}

{$var%Pattern} Remove from $var the shortest part of $Pattern that matches the back end of $var.

{$var%%Pattern} Remove from $var the longest part of $Pattern that matches the back end of $var.[/code]

Pošto se koristio % operator (${base%.*}) znači idemo s desne strane, dok ne naiđemo na prvu tačku.
Radi i sa razmacima, zarezima i sl u nazivu datoteka (tako da fakat ne kontam “poentu”)

Anyway, može se sad izmisliti dosta razloga zašto taj i taj pristup ne bi radio, a neki super cool regularni izraz (po narodski kobasica) radi uvijek i zauvijek, ali mislim da u programiranju nema apsolutnih istina, samo previše načina da se uradi jedna stvar :wink:

Mislio sam npr. na slučaj
Enterprise 1x03.Fight or flight.The Second Edition.srt
Tvoj kod bi protumačio “Enterprise 1x03.Fight or flight” kao prefix a “The Second Edition” kao base. Rješenje je da se ide s lijeve strane za prefix a s desne za ekstenziju, ali je sve to skupa IMHO totalno neprirodan način razmišljanja. Prednost regexa je što možeš zadati format koji mora zadovoljiti čitav string umjesto da “ideš sa neke strane”. Uostalom šta fali jednom malom regex tutorijalu :slight_smile: Sasvim je svejedno da li koristiš kobasicu ili jedan jedini znak ako ne znaš šta taj znak znači :slight_smile:

Pa opet ne čitaš šta piše, da pojednostavimo, probaj:

$ A="Enterprise 1x03.Fight or flight.The Second Edition.srt" $ echo ${A%.*} Enterprise 1x03.Fight or flight.The Second Edition $ echo ${A%.*.*} Enterprise 1x03.Fight or flight
Što će nam regexi kad padamo na jednostavnim stvarima (griješiti je ljudski)

Prednost regexa u ovom konkretnom slučaju jeste da je komplikovaniji. Vjerujem da postoji i vrijeme i mjesto za regexe (u paklu?, šala mala), ali u dosta slučajeva upotreba regularnih izraza kosi se sa KISS principom. Ruglarni izrazi su clever (u Python smislu te riječi).

Ne kontam kakve veze ima ovaj zadnji komad koda sa činjenicom da tvoj program ne radi (ni prvi ni drugi) sa primjerom koji sam dao?

/home/user/tmp> touch "Enterprise 1x03.Fight or flight.The Second Edition.srt" /home/user/tmp> touch "Enterprise 1x03.avi" /home/user/tmp> for f in *.srt; do mv "${f%.*.*}.avi" "${f%.*}.avi"; done mv: cannot stat `Enterprise 1x03.Fight or flight.avi': No such file or directory

Ako ne vidiš vezu, onda ne znam, možda posjeta očnom? (lol, nisam mogao propustit priliku)

Radi i sa primjerom sa početka threada, i sa imaginarnim primjerom sa više tačaka.

Dodao sam output u poruku. Sjedi sad fino, uzmi čašu vode i šećera i pročitaj čitav thread od početka…

Nastavak:

[code]/home/user/tmp> for f in *.srt; do

base=${f%.*}
prefix=${base%.*}
mv "$prefix.avi" "$base.avi"

done
mv: cannot stat `Enterprise 1x03.Fight or flight.avi’: No such file or directory[/code]

Promijenio si osnovne postavke primjera, ekvivalentno tome moraju se promijeniti patterni u kodu:

for f in *.srt; do mv "${f%.*.*.*}.avi" "${f%.*}.avi"; done ili for f in *.srt; do mv "${f%%.*.*}.avi" "${f%.*}.avi"; done
Znači možemo koristiti ili % ili %% kako nam paše. But that’s not the point, ti uporno odbijaš piznati da su u konkretnom slučaju regularni izrazi totalni overkill, te da nema nekih imaginarnih problema sa brojem tačaka, razmacima i sl. kad se radi direktno u bashu.

Edit:
P.S. prvobitno rješenje je pisano za konkretan problem, čovjek se već izjasnio da radi, šta pokušavaš dokazati? :smiley:

Obrazloži zašto su overkill? Ja recimo nikad nisam čuo za operatore ${…%…} i ${…%%…} do ovih tvojih primjera niti me interesuje da to učim, s druge strane Perl-kompatibilni regexi su mi savršeno logični. regex je možda par puta sporiji od globbinga, ali na svim mašinama novijim od 286ice to se ne bi trebalo primijetiti.

O “imaginarnim problemima” reći ću samo da u tom prvom kodu praviš istu grešku :slight_smile: jer će sad on raditi samo za slučajeve kada imaš tačno dvije tačke između prefixa i ekstenzije. Nikako da uvidiš problemsku logiku a to je da:

  • prefix ne sadrži tačke
  • naziv epizode može sadržavati bilo šta
  • ekstenzija je fiksna
    regex ti omogućuje da napišeš kod koji tačno odražava ovo gore nabrojano, dok ćeš ti uporno pokušavati čekićem koji se zove bash zakucati sve što liči na ekser zato što ti tvoja religija ne dozvoljava da naučiš jedan jednostavan i moćan alat :slight_smile: i poslije se čuditi neočekivanim rezultatima.

Btw no comment na “promijenio si osnovne postavke” pročitaj ponovo:

[quote]Edit:
P.S. prvobitno rješenje je pisano za konkretan problem, čovjek se već izjasnio da radi, šta pokušavaš dokazati? :-D[/quote]
A ja sam samo napisao jedno alternativno rješenje za isti problem koje isto tako radi, šta ti pokušavaš dokazati??? :stuck_out_tongue: