From marcelo.magallon en gmail.com Mon Apr 2 12:45:28 2012 From: marcelo.magallon en gmail.com (Marcelo) Date: Mon, 2 Apr 2012 13:45:28 -0600 Subject: Aprendiendo Perl, el reto: Encontrar duplicados In-Reply-To: References: Message-ID: Tal vez hay que ofrecer algo de material para poder hablar al respecto :-) Como brian todavía no hay publicado sus comentarios, pongo mi propia solución que sí es recursiva. Si le pasan el nombre de un directorio en la línea de comandos va a buscar duplicados en ese directorio y todo lo que contenga, sino va a buscarlos en el directorio actual. #!/usr/bin/env perl use Modern::Perl '2012'; use Digest::MD5; use File::Find; sub get_checksum($) { open my $fh, "<", $_[0] or return undef; local $/; return Digest::MD5::md5_hex(<$fh>); } push @ARGV, '.' unless scalar @ARGV; my %checksum; find({ wanted => sub { return if -d $_ || ! -r $_; return unless defined (my $key = get_checksum($_)); if (exists $checksum{$key}) { # Ya vimos otro archivo con el mismo checksum say $checksum{$key}, " ", $_; } else { $checksum{$key} = $_; } }, no_chdir => 1, }, @ARGV); From dryajov en gmail.com Tue Apr 3 16:19:17 2012 From: dryajov en gmail.com (Dmitriy Ryajov) Date: Tue, 03 Apr 2012 17:19:17 -0600 Subject: Comunidad de Perl en CR y =?ISO-8859-1?Q?pr=F3ximas_reuniones_?= =?ISO-8859-1?Q?de_CostaRica=2Epm?= Message-ID: <4F7B8575.2000403@gmail.com> Hola Gente, Me preguntaba que tan grande es la comunidad de Perl en Costa Rica, y cuando sera la próxima reunión de CostaRica.pm? Gracias, Dmitriy. From javier.tia en gmail.com Tue Apr 3 17:17:19 2012 From: javier.tia en gmail.com (=?UTF-8?Q?Javier_Ti=C3=A1?=) Date: Tue, 3 Apr 2012 18:17:19 -0600 Subject: Aprendiendo Perl, el reto: Encontrar duplicados In-Reply-To: References: Message-ID: Hola: Yo me sumo y agrego otra solución. Es recursivo y debes siempre pasarle el camino donde quieres buscar los archivos duplicados. ------------------------------ 8< ------------------------------ #!/usr/bin/env perl use strict; use warnings; use File::Find; use File::Basename; use Digest::MD5; ($#ARGV == 0) or die "Usage: " . basename($0) . " \n"; my %hashes = (); find \&wanted, @ARGV; sub get_hash($) { open(FILE, $_); return Digest::MD5->new->addfile(*FILE)->hexdigest; } sub wanted { $hashes{$File::Find::name} = get_hash($_) if -f $_; } for my $path (sort { $hashes{$a} cmp $hashes{$b} } keys %hashes) { print "$path\n" if ((grep {/$hashes{$path}/} values %hashes) > 1); } ------------------------------ >8 ------------------------------ P.D: Mi post en http://www.learning-perl.com/?p=286 está en espera de aprobación. -- Javier Tiá From marcelo.magallon en gmail.com Wed Apr 4 19:40:18 2012 From: marcelo.magallon en gmail.com (Marcelo) Date: Wed, 4 Apr 2012 20:40:18 -0600 Subject: Aprendiendo Perl, el reto: Encontrar duplicados In-Reply-To: References: Message-ID: ¡Hola! 2012/4/3 Javier Tiá : > sub get_hash($) Esta es una mala costumbre mía que me ha costado mucho soltar. Los prototipos para las subrutinas en Perl pueden ser contraproducentes. En este caso el efecto del prototipo es que Perl reclama si uno no llama a la subrutina con exactamente un argumento, y es la razón por la que a mi me cuesta deshacerme de esa costumbre. Sin embargo en este caso: sub magia(\@\@) tiene un efecto inesperado. Si uno invoca a esta función así: magia(@a, @b); cualquier desarrollador de Perl viendo esa línea simplemente asumirá que @a y @b se van a "juntar" en un solo gran array en @_ dentro de la subrutina, pero por el prototipo lo que Perl realmente hace es pasar los dos arrays como referencias. Uno puede argumentar que eso es bueno porque es exactamente lo que quien escribió el código espera que suceda, pero no es evidente para quien está leyendo el código. Esto en cambio es claro: magia(\@a, \@b); Hay otra razón para no usar prototipos: no hacen lo que la mayoría queremos que hagan. Lo que un prototipo realmente hace es imponer contexto, no requerir una cantidad particular de argumentos como señalé antes. Intuitivamente uno espera que Perl reclame con este programa: #!/usr/bin/env perl use Modern::Perl; sub n($) { my $arg = shift; say $arg; } my $a = 1; my @b = (0, 0, 0); n($a); n(@b); pero no, este programa no solo corre sin objecciones sino que hace exactamente lo dice ahí que tiene que hacer. Si reclama en este caso por ejemplo: n($a, @b); y reclama exactamente en la forma que uno quiere que reclame: Too many arguments for main::n at [...], near "@b)" por eso cuesta tanto abandonarlos. > { >    open(FILE, $_); >    return Digest::MD5->new->addfile(*FILE)->hexdigest; > } En general uno no debería usar otra cosa que no sea la forma de tres argumentos de open, así: open(FILE, "<", $_) Otra vez: esto hace explícito que es lo que uno pretende. La otra cosa es que uno no debería usar "palabras chingas" (barewords) como "FILE". En el caso de este código en particular, lo que está sucediendo es que se abre el archivo, se lee y se deja abierto hasta la siguiente llamada de esa función. Hasta ese momento se cierra el archivo porque Perl ocupa el filehandle (FILE). Se abre el siguiente archivo y queda abierto hasta la siguiente vez que se llame esa función. Esto sucede porque el "scope" de *FILE es el paquete, no la función. Y el problema con los barewords es exactamente ese. Y una cosa que tal vez es menos cosmética es el uso de $_. $_ *no* es el argumento de la función. Si uno va a: $hashes{$File::Find::name} = get_hash($_) if -f $_; y cambia "get_hash($_)" por "get_hash('el cielo pintado de azul')" se ve que el código funciona exactamente igual. En la función $_ sigue siendo la misma variable que en el entorno donde fue llamada. No solo tiene el mismo valor, es la misma variable. Este programa puede resultar sorpresivo: #!/usr/bin/env perl use Modern::Perl; sub n { $_ = 2; } $_ = 1; n; say; Saludos, Marcelo From dryajov en gmail.com Thu Apr 5 01:30:39 2012 From: dryajov en gmail.com (Dmitriy Ryajov) Date: Thu, 05 Apr 2012 02:30:39 -0600 Subject: Aprendiendo Perl, el reto: Encontrar duplicados In-Reply-To: References: Message-ID: <4F7D582F.10808@gmail.com> Aquí esta mi versión. No hago uso de File::Find si no, utilizo opendir y readdir directamente, esto para propósitos ilustrativos. Esta versión, recorre (recursivamente) una lista de directorios que se pasa como argumento o utiliza el directorio actual, desde donde se ejecuto el script. <==============================================================> #!/usr/bin/env perl use strict; use warnings; use Digest::MD5; use Cwd; my @directories = (); # list of scanned directories my @dirs = @ARGV; @dirs = ( getcwd ) unless scalar @dirs; for my $dir ( @dirs ) { scan_dir( $dir ); } for my $dir_struct ( @directories ) { print "Found duplicates in directory $dir_struct->{name}\n"; print "File: $_\n" for @{$dir_struct->{files}}; } sub scan_dir { my $directory = shift; $directory =~ s|/?$||g; # remove trailing / # open dir for scanning opendir my $dh, $directory or print "Error opening dir: $directory\n$!" && return; # don't die, we just want to skip this dir my $dir_struct = { name => $directory, # name of the scanned dir files => [], # list of scanned files }; my %dup_files = (); for my $file ( readdir( $dh ) ) { next if $file =~ /^\.{1,2}$/; # skip current and parrent dir $file = "$directory/$file"; # fix up file name to full path if( -d $file ) { # recurse if it's a directory scan_dir($file); next; } next if !-r $file; # skip non readble files my $checksum = chekcsum( $file ); if ( !$dup_files{$checksum} ) { $dup_files{$checksum} = $file; next; } push @{$dir_struct->{files}}, $file; } # store it for later use push @directories, $dir_struct if scalar @{$dir_struct->{files}}; } sub chekcsum { open( my $fh, '<', shift ) or die $!; binmode($fh); return Digest::MD5->new->addfile($fh)->hexdigest; } <==============================================================> Saludos, Dmitriy Ryajov. On 03/27/2012 09:15 AM, Marcelo wrote: > Hola, > > brian d foy[0] comenzó a publicar en http://www.learning-perl.com/ una > serie de retos para la gente aprendiendo Perl. Pensé que para alguna > gente podría ser útil tener el reto disponible en Español y no en > Inglés, además de poder conversar sobre las soluciones también en > Español. Hasta que no monte otra cosa, les propongo hacerlo mediante > esta lista, si alguno tiene interés. > > A continuación la traducción del post que brian publicó en > http://www.learning-perl.com/?p=286 > > ------------------------------ 8< ------------------------------ > > Este es el segundo reto para novatos. Voy a darles un problema que > deberían poder resolver solo con las cosas presentes en "Learning > Perl" (incluyendo el uso de módulos, es decir, la mayoría de Perl). > Más o menos una semana después publicaré una solución (NdT: me > comprometo a traducir las soluciones también). > > Para este reto, dado un único directorio conteniendo archivos > posiblemente duplicados, encuentre los archivos que pueden ser > duplicados. Solo debe imprimir los archivos duplicados e imprimir sus > nombres. Si desea remover los duplicados, ¡asegúrese de tener un > backup! > > Existen algunos módulos que pueden resultar útiles: > > Digest::MD5 > Digest::SHA1 > > Si se encuentra especialmente motivado, busque también en los > subdirectorios que encuentre. > > ------------------------------>8 ------------------------------ > > Saludos y que se diviertan, > > Marcelo > > PS: Como pueden ver en el blog de Learning Perl, la gente que quiere > recibir retroalimentación publica sus soluciones allí. Sería > buenísimo si la gente por acá hiciese lo mismo y los demás les den > opiniones. > > [0] brian es coautor de "Learning Perl" en su última edición. Él > prefiere escribir su nombre así como aparece acá, no estoy siendo > perezoso con las mayúsculas :-) > __ > Costarica-pm en pm.org > http://mail.pm.org/mailman/listinfo/costarica-pm From javier.tia en gmail.com Thu Apr 5 19:13:56 2012 From: javier.tia en gmail.com (=?UTF-8?Q?Javier_Ti=C3=A1?=) Date: Thu, 5 Apr 2012 20:13:56 -0600 Subject: Aprendiendo Perl, el reto: Encontrar duplicados In-Reply-To: References: Message-ID: Hola nuevamente, 2012/4/4 Marcelo : > ¡Hola! > > 2012/4/3 Javier Tiá : > >> sub get_hash($) > > Esta es una mala costumbre mía que me ha costado mucho soltar.  Los > prototipos para las subrutinas en Perl pueden ser contraproducentes. > En este caso el efecto del prototipo es que Perl reclama si uno no > llama a la subrutina con exactamente un argumento, y es la razón por > la que a mi me cuesta deshacerme de esa costumbre. Me parece, es una mala costumbre de muchos por la falta de claridad en el uso de los prototipos en Perl. > Sin embargo en este caso: > > sub magia(\@\@) > > tiene un efecto inesperado.  Si uno invoca a esta función así: > > magia(@a, @b); > > cualquier desarrollador de Perl viendo esa línea simplemente asumirá > que @a y @b se van a "juntar" en un solo gran array en @_ dentro de la > subrutina, pero por el prototipo lo que Perl realmente hace es pasar > los dos arrays como referencias.  Uno puede argumentar que eso es > bueno porque es exactamente lo que quien escribió el código espera que > suceda, pero no es evidente para quien está leyendo el código.  Esto > en cambio es claro: > > magia(\@a, \@b); > > Hay otra razón para no usar prototipos: no hacen lo que la mayoría > queremos que hagan.  Lo que un prototipo realmente hace es imponer > contexto, no requerir una cantidad particular de argumentos como > señalé antes.  Intuitivamente uno espera que Perl reclame con este > programa: > > #!/usr/bin/env perl > > use Modern::Perl; > > sub n($) > { >    my $arg = shift; >    say $arg; > } > > my $a = 1; > my @b = (0, 0, 0); > > n($a); > n(@b); > > pero no, este programa no solo corre sin objecciones sino que hace > exactamente lo dice ahí que tiene que hacer.  Si reclama en este caso > por ejemplo: > > n($a, @b); > > y reclama exactamente en la forma que uno quiere que reclame: > > Too many arguments for main::n at [...], near "@b)" > > por eso cuesta tanto abandonarlos. > >> { >>    open(FILE, $_); >>    return Digest::MD5->new->addfile(*FILE)->hexdigest; >> } > > En general uno no debería usar otra cosa que no sea la forma de tres > argumentos de open, así: > > open(FILE, "<", $_) > > Otra vez: esto hace explícito que es lo que uno pretende. > > La otra cosa es que uno no debería usar "palabras chingas" (barewords) > como "FILE".  En el caso de este código en particular, lo que está > sucediendo es que se abre el archivo, se lee y se deja abierto hasta > la siguiente llamada de esa función.  Hasta ese momento se cierra el > archivo porque Perl ocupa el filehandle (FILE).  Se abre el siguiente > archivo y queda abierto hasta la siguiente vez que se llame esa > función.  Esto sucede porque el "scope" de *FILE es el paquete, no la > función.  Y el problema con los barewords es exactamente ese. Buen consejo, anotado para hacer mejor uso de 'open' en las próximas líneas de Perl. > Y una cosa que tal vez es menos cosmética es el uso de $_.  $_ *no* es > el argumento de la función. > > Si uno va a: > >   $hashes{$File::Find::name} = get_hash($_) if -f $_; > > y cambia "get_hash($_)" por "get_hash('el cielo pintado de azul')" se > ve que el código funciona exactamente igual.  En la función $_ sigue > siendo la misma variable que en el entorno donde fue llamada.  No solo > tiene el mismo valor, es la misma variable. Esta parte me resulta confusa. Puedo usar "get_hash('el cielo pintado de azul')" o "get_hash($foo)" que esperaría el mismo resultado, pero si uso "get_hash" o "get_hash()" me da error. Si no importa tanto el parámetro dentro de la subrutina, ¿Por qué obligatoriamente tengo que pasarle 'algo', con cierta tendencia a 'cualquier cosa', como parámetro dentro una subrutina? Espero esa sea la pregunta correcta :) > Este programa puede resultar sorpresivo: > > #!/usr/bin/env perl > > use Modern::Perl; > > sub n { $_ = 2; } > > $_ = 1; > n; > say; Este ejemplo me gustó, me llevó a estudiarme un poco más el alcance(scope) de las variables y la influencia en ellas de las órdenes internas('my' y 'local'). Gracias y saludos, -- Javier Tiá From javier.tia en gmail.com Thu Apr 5 21:34:16 2012 From: javier.tia en gmail.com (=?UTF-8?Q?Javier_Ti=C3=A1?=) Date: Thu, 5 Apr 2012 22:34:16 -0600 Subject: Aprendiendo Perl, el reto: Encontrar duplicados In-Reply-To: <20120406032618.GA24076@esk> References: <20120406032618.GA24076@esk> Message-ID: 2012/4/5 Marcelo E. Magallon : >  Curiosamente en Learning Perl el primer ejemplo de open es con >  barewords y solo dos argumentos, y luego de eso pasan muchas >  páginas antes de siquiera mencionar open con referencias.  Esto >  de hecho ha sido motivo de discusión aquí y allá y brian d foy >  dice que primero que nada, uno no puede ignorar el hecho que >  open con barewords existe, y que si la gente quiere aprender >  Perl tiene que saber que eso existe, aún cuando ellos mismos >  nunca vayan a escribir ni una sola vez open de esa forma. En la edición 4th de Learning Perl, es la que tengo, todos los ejemplos vistos usan barewords. Uso mayormente Perl v5.8. >> Esta parte me resulta confusa. >> Puedo usar "get_hash('el cielo pintado de azul')" o >> "get_hash($foo)" que esperaría el mismo resultado, pero si uso >> "get_hash" o "get_hash()" me da error. > >  Mea culpa, no me expliqué bien.  El problema al que yo me >  pretendía referir no está en la llamada a get_hash, está en la >  implementación: > >    sub get_hash($) >    { >       open(FILE, $_); >       return Digest::MD5->new->addfile(*FILE)->hexdigest; >    } > >  ese "$_" en open se refiere a la variable $_ en el sitio de la >  llamada: > >    $hashes{$File::Find::name} = get_hash($_) if -f $_; > >  y lo que quise decir es que el argumento de get_hash es >  completamente ignorado.  En get_hash el primer argumento de la >  función sería $_[0], y la expresión más idiomática es: > >    my $filename = shift; >    open(FILE, $filename); >    return Digest::MD5->new->addfile(*FILE)->hexdigest; > >  La razón por la que te da error al tratar de usar get_hash o >  get_hash() es porque el prototipo dice que esa función debe ser >  llamada con un argumento escalar. Escribiéndole así: sub get_hash { my $filename = shift; open(FILE, $filename); return Digest::MD5->new->addfile(*FILE)->hexdigest; } Se vería mejor y sería otra razón para no usar prototipo :) Corríjeme Marcelo si estoy equivocado, pero me parece estar viendo como buena práctica: NO usar prototipos. Saludos, Javier From marcelo.magallon en gmail.com Thu Apr 5 17:42:02 2012 From: marcelo.magallon en gmail.com (Marcelo E. Magallon) Date: Thu, 5 Apr 2012 18:42:02 -0600 Subject: Aprendiendo Perl, el reto: Encontrar duplicados In-Reply-To: <4F7D582F.10808@gmail.com> References: <4F7D582F.10808@gmail.com> Message-ID: <20120406004159.GA20663@esk> Hola, On Thu, Apr 05, 2012 at 02:30:39AM -0600, Dmitriy Ryajov wrote: > opendir my $dh, $directory or > print "Error opening dir: $directory\n$!" && > return; # don't die, we just want to skip this dir Si bien la construcción es perfectamente válida, en general cosas estilo "a or b || c" son mejor evitarlas. No me refiero a "a or b" sino a la mezcla de operadores booleanos de baja precedencia (or, and, not) con operadores de alta precedencia (||, &&, !). La razón es mantenibilidad del código. Consideren por ejemplo este ejemplo absurdo: ---------- 8< ---------- sub test { 0 or say 1 && return; } test; ---------- >8 ---------- ¿Qué pasa cuando otra persona venga detrás y haga esto? ---------- 8< ---------- sub test { 0 or say 1, " ", 2 && return; } test; ---------- >8 ---------- Saludos y gracias por el aporte, Marcelo From marcelo.magallon en gmail.com Mon Apr 16 18:50:44 2012 From: marcelo.magallon en gmail.com (Marcelo) Date: Tue, 17 Apr 2012 01:50:44 -0000 Subject: Aprendiendo Perl, el reto: Encontrar duplicados Message-ID: Hola, brian d foy[0] comenzó a publicar en http://www.learning-perl.com/ una serie de retos para la gente aprendiendo Perl. Pensé que para alguna gente podría ser útil tener el reto disponible en Español y no en Inglés, además de poder conversar sobre las soluciones también en Español. Hasta que no monte otra cosa, les propongo hacerlo mediante esta lista, si alguno tiene interés. A continuación la traducción del post que brian publicó en http://www.learning-perl.com/?p=286 ------------------------------ 8< ------------------------------ Este es el segundo reto para novatos. Voy a darles un problema que deberían poder resolver solo con las cosas presentes en "Learning Perl" (incluyendo el uso de módulos, es decir, la mayoría de Perl). Más o menos una semana después publicaré una solución (NdT: me comprometo a traducir las soluciones también). Para este reto, dado un único directorio conteniendo archivos posiblemente duplicados, encuentre los archivos que pueden ser duplicados. Solo debe imprimir los archivos duplicados e imprimir sus nombres. Si desea remover los duplicados, ¡asegúrese de tener un backup! Existen algunos módulos que pueden resultar útiles: Digest::MD5 Digest::SHA1 Si se encuentra especialmente motivado, busque también en los subdirectorios que encuentre. ------------------------------ >8 ------------------------------ Saludos y que se diviertan, Marcelo PS: Como pueden ver en el blog de Learning Perl, la gente que quiere recibir retroalimentación publica sus soluciones allí. Sería buenísimo si la gente por acá hiciese lo mismo y los demás les den opiniones. [0] brian es coautor de "Learning Perl" en su última edición. Él prefiere escribir su nombre así como aparece acá, no estoy siendo perezoso con las mayúsculas :-) From marcelo.magallon en gmail.com Thu Apr 5 17:44:30 2012 From: marcelo.magallon en gmail.com (Marcelo E. Magallon) Date: Thu, 5 Apr 2012 18:44:30 -0600 Subject: Comunidad de Perl en =?iso-8859-1?Q?CR?= =?iso-8859-1?Q?_y_pr=F3ximas?= reuniones de CostaRica.pm In-Reply-To: <4F7B8575.2000403@gmail.com> References: <4F7B8575.2000403@gmail.com> Message-ID: <20120406004430.GB20663@esk> On Tue, Apr 03, 2012 at 05:19:17PM -0600, Dmitriy Ryajov wrote: > Me preguntaba que tan grande es la comunidad de Perl en Costa > Rica, y cuando sera la próxima reunión de CostaRica.pm? Depende de cómo se le mire. Hay mucha gente que usa Perl, ya sea por gusto o por trabajo, pero en términos de comunidad hay poca actividad. Eso por supuesto tiene arreglo :-) No hay una próxima reunión agendada, es cosa de ponerse de acuerdo. Tal vez si alguien propone un tema sea más fácil organizarla (y "socializar" es un tema válido). Saludos, Marcelo From marcelo.magallon en gmail.com Mon Apr 16 10:03:58 2012 From: marcelo.magallon en gmail.com (Marcelo E. Magallon) Date: Mon, 16 Apr 2012 11:03:58 -0600 Subject: Aprendiendo Perl, el reto: tripwire Message-ID: <20120416170358.GA3789@esk> En el reto anterior de "Aprendiendo Perl"[0] se pedía encontrar archivos duplicados. Este reto requiere de algunas de las cosas que se hicieron ahí, pero para un propósito distinto. Escriba un programa que monitoree un directorio para encontrar cualquier archivo que cambie. Programas como tripwire implementan esto guardando meta información del archivo la primera vez que corren y luego revisan que esa información coincida posteriormente. Por ejemplo, el tamaño y "digest" SHA1 deben permanecer iguales. También se podría guardar el contenido original, pero eso no es muy conveniente. Dado que usted está al nivel de Aprendiendo Perl, no podemos pedir demasiado o juzgarlo fuertemente. Buena parte del problema está en guardar los datos y leerlos posteriormente. Una pista: cree un archivo plano para guardar los datos "buenos" en la primera corrida, y luego lea este archivo durante la segunda corrida: 1 #nombre:tamaño:SHA1 2 file.txt:1023:53a0935982ae11a4784d51aa696733c947c0614f ¿Cómo va a manejar la seguridad de este archivo después de crearlo? Como ejemplo, puede consultar CPAN::Checksums[1], que se encarga de la misma tarea para los módulos de CPAN. Hay muchas formas en las que puede utilizar esto. Puede ejecutarlo en forma periódica desde cron, por ejemplo, pero también puede hacer un 'daemon' que corra de forma contínua y que esté revisando de forma periódica. Una vez que encuentre un cambio, puede reportarlo de muchas formas, pero vamos a pedir solo que imprima una línea en la terminal, que puede verse algo así como: 1 file.txt cambió. 2 3 Era: 4 Tamaño: 1023 bytes 5 SHA1: 53a0935982ae11a4784d51aa696733c947c0614f 6 7 Ahora es: 8 Tamaño: 2001 bytes 9 SHA1: 730c6983bb9f942ef5cf6c174d76ad0c1594c1a7 [0] http://www.learning-perl.com/?p=286 [1] https://www.metacpan.org/module/CPAN::Checksums -------------------- 8< -------------------- Ese es el nuevo reto que publició brian en http://www.learning-perl.com/?p=287. Como siempre, quien quiera publicar sus propias soluciones acá en la lista de correo es bienvenido a hacerlo, y quien quiera comentar las soluciones presentadas es igualmente bienvenido. From marcelo.magallon en gmail.com Mon Apr 16 18:53:34 2012 From: marcelo.magallon en gmail.com (Marcelo E. Magallon) Date: Mon, 16 Apr 2012 19:53:34 -0600 Subject: Disculpas por los mensajes duplicados Message-ID: <20120417015333.GA6357@esk> Hola, disculpas si les llegan algunos mensajes más de una vez. Me acabo de dar cuenta que algunos mensajes míos nunca llegaron a la lista y reenvié los que pensé que tendría sentido reenviar. Saludos, Marcelo From marcelo.magallon en gmail.com Sat Apr 21 16:48:55 2012 From: marcelo.magallon en gmail.com (Marcelo E. Magallon) Date: Sat, 21 Apr 2012 17:48:55 -0600 Subject: Aprendiendo Perl, el reto: tripwire In-Reply-To: <20120416170358.GA3789@esk> References: <20120416170358.GA3789@esk> Message-ID: <20120421234854.GA11642@esk> On Mon, Apr 16, 2012 at 11:03:58AM -0600, Marcelo E. Magallon wrote: > Escriba un programa que monitoree un directorio para encontrar > cualquier archivo que cambie. Mi aproximación a una solución. No "monitorea" un directorio exactamente como lo plantea el reto original, sino que lee (recursivamente) un directorio y guarda un archivo con la información de cada archivo en ese directorio. Si el archivo ya existe entonces lo que hace es verificar los cambios que ocurrieron. Tiene varias deficiencias, pero implementa el concepto básico. Saludos, Marcelo ------------------------------ >8 ------------------------------ #!/usr/bin/env perl use Modern::Perl; use Digest::MD5; use File::Find; use Getopt::Std; use constant DATAFILE => ".checksums"; sub get_checksum { my $filename = shift; open my $fh, "<", $filename or return; local $/; return Digest::MD5::md5_hex(<$fh>); } sub get_checksums { my $info = {}; find({ wanted => sub { return if -d $_ || ! -r $_; return unless defined (my $checksum = get_checksum($_)); my $size = -s $_; $info->{$_} = "$size:$checksum"; }, no_chdir => 1, }, @_); return $info; } sub store_checksums { my $datafile = shift; my $info = shift; open my $fh, ">", $datafile; foreach my $filename (keys %$info) { say $fh "$filename:$info->{$filename}" } } sub read_checksums { my $datafile = shift; my $info = {}; open my $fh, "<", $datafile; while (<$fh>) { chomp; my ($filename, $data) = split ':', $_, 2; $info->{$filename} = $data; } return $info; } sub verify_checksums { my $old = read_checksums shift; my $new = shift; foreach my $filename (keys { map { $_ => 1 } (keys %$new, keys %$old) }) { if (exists $new->{$filename} && exists $old->{$filename}) { my ($odata, $ndata) = ($old->{$filename}, $new->{$filename}); if ($odata ne $ndata) { say "$filename changed from $odata to $ndata"; } } elsif (exists $new->{$filename}) { say "$filename is new"; } else { say "$filename dissapeared"; } } } my %opts = ( f => DATAFILE ); getopts('rf:', \%opts); push @ARGV, '.' unless scalar @ARGV; my $checksums = get_checksums @ARGV; if (exists $opts{'r'} || ! -e $opts{'f'}) { store_checksums $opts{'f'}, $checksums; } else { verify_checksums $opts{'f'}, $checksums; } ------------------------------ 8< ------------------------------ From marcelo.magallon en gmail.com Sat Apr 21 17:08:03 2012 From: marcelo.magallon en gmail.com (Marcelo E. Magallon) Date: Sat, 21 Apr 2012 18:08:03 -0600 Subject: Perl Ironman Message-ID: <20120422000802.GB11642@esk> Hola, para los que tengan inclinación por escribir, quería comentarles que existe una iniciativa de "Enlightened Perl"[0] llamada "Perl Ironman". Consiste básicamente en mantener un blog relacionado con Perl. Puede ser en cualquier idioma y mantenerse en cualquier plataforma (http://blogs.perl.org/ es una buena opción), el único "requisito" es mantener una frecuencia de al menos 4 posts cada 32 días con un máximo de 10 días entre posts. Si lo quieren ver así es más bien como un reto. Una buena forma de colaborar con la comunidad sería mantener el blog en Español, ya de que esos hay muy pocos. Encuentran los blogs respectivos agregados en [1] y los detalles de la iniciativa en [2]. Saludos, Marcelo [0] http://www.enlightenedperl.org/ [1] http://ironman.enlightenedperl.org/ [2] http://www.enlightenedperl.org/ironman.html From marcelo.magallon en gmail.com Sun Apr 29 16:56:35 2012 From: marcelo.magallon en gmail.com (Marcelo) Date: Sun, 29 Apr 2012 17:56:35 -0600 Subject: CostaRica.pm en Google+ Message-ID: Hola, para aquellos de ustedes que utilicen Google+, creé una página para el grupo en ese sitio. La página es: https://plus.google.com/111416973020428896068 Pueden agregar la página a sus círculos y así demostrar su interés en el grupo. En la página solo saldrá la cantidad de usuarios que la han agregado a uno de sus círculos, y solo si ustedes lo tienen así configurado, aparecerán también listados dentro de las personas que incluyen a la página en sus círculos. Notarán que hay un espacio en blanco en la "foto" que aparece en la página. Si algún creativo quiere proponer ideas para ocupar ese espacio con algo alusivo a Costa Rica, o proponer una imagen totalmente distinta, será bienvenido. Saludos, Marcelo