perl find directory-traversal

¿Por qué no puedo eliminar este directorio vacío en Perl?



find directory-traversal (4)

Estoy convirtiendo un script de Linux de http://www.perlmonks.org/index.pl?node_id=217166 específicamente esto:

#!/usr/bin/perl -w use strict; use Getopt::Std; use File::Find; @ARGV > 0 and getopts(''a:'', /my %opt) or die << "USAGE"; # Deletes any old files from the directory tree(s) given and # removes empty directories en passant. usage: $0 [-a maxage] directory [directory ...] -a maximum age in days, default is 120 USAGE my $max_age_days = $opt{a} || 120; find({ wanted => sub { unlink if -f $_ and -M _ > $max_age_days }, postprocess => sub { rmdir $File::Find::dir }, }, @ARGV);

mi intento es:

#!/usr/bin/perl -w use strict; use Getopt::Std; use File::Find; @ARGV > 0 and getopts(''a:'', /my %opt) or die << "USAGE"; # Deletes any old files from the directory tree(s) given and # removes empty directories en passant. usage: $0 [-a maxage] directory [directory ...] -a maximum age in days, default is 120 USAGE my $max_age_days = $opt{a} || 120; find({ wanted => sub { unlink if -f $_ and -M _ > $max_age_days }, # postprocess => sub { rmdir $File::Find::dir }, postprocess => sub { my $expr = "$File::Find::dir"; $expr =~ s///////g; # replace / with / print "rmdir $expr/n"; `rmdir $expr`; }, }, @ARGV);

Sin embargo, recibo un error cuando el script intenta eliminar un directorio que dice que el directorio está siendo utilizado por otro proceso (cuando no lo está). ¿Algunas ideas? Estoy ejecutando la secuencia de comandos en Windows Server 2003 SP2 de 64 bits con ActiveState 5.10.

¡Gracias!


Gracias por todas sus respuestas. Mi script final se ve así:

#!/usr/bin/perl -w use strict; use warnings; use Getopt::Std; use File::Find; use Win32::OLE; @ARGV > 0 and getopts(''a:'', /my %opt) or die << "USAGE"; Deletes any old files from the directory tree(s) given and removes empty directories en passant. usage: $0 [-a maxage] directory [directory ...] -a maximum age in days, default is 30 USAGE my $max_age_days = $opt{a} || 30; my @dir_list = undef; find({ wanted => sub { if (-f $_ and -M _ > $max_age_days) { unlink $_ or LogError ("$0: Could not delete $_ ($!)")}}, postprocess => sub {push(@dir_list,$File::Find::dir)}, }, @ARGV); if (@dir_list) {foreach my $thisdir (@dir_list) { rmdir $thisdir if defined ($thisdir)}} ############ sub LogError { my ($strDescr) = @_; use constant EVENT_SUCCESS => 0; use constant EVENT_ERROR => 1; use constant EVENT_WARNING => 3; use constant EVENT_INFO => 4; my $objWSHShell = Win32::OLE->new(''WScript.Shell''); $objWSHShell->LogEvent(EVENT_ERROR, $strDescr); }

Parece funcionar bien, ¿puedes pensar en alguna forma de mejorarlo?


La versión perlmonks utiliza un método Perl "rmdir" para realizar la eliminación. Su versión genera una subshell con comillas inversas. Por lo tanto, es posible que el mensaje sea correcto: Perl aún está utilizando el directorio cuando el rmdir está tratando de usarlo.


Solo unas pocas notas:

  1. No es necesario voltear el / a un /. Perl entiende que / es un separador de directorios, incluso en Windows.
  2. rmdir es un Perl incorporado, no es necesario que lo llames con palos de retroceso.

De esta documentación

proceso después de

El valor debe ser una referencia de código. Se invoca justo antes de salir del directorio actualmente procesado . Se llama en contexto vacío sin argumentos. El nombre del directorio actual se encuentra en $ File :: Find :: dir. Este gancho es útil para resumir un directorio, como calcular el uso del disco. Cuando follow o follow_fast están vigentes, el postproceso no es operativo.

Esto significa que su propio código aún está usando el directorio cuando intenta eliminarlo. Intente crear una lista de nombres e iterar a través de eso después de la llamada para encontrar.

Otra posible solución es utilizar la opción no_chdir para evitar tener que encontrar el uso de los directorios que desea eliminar.

EDITAR: Este comentario también es relevante, así que lo estoy promocionando al cuerpo de la respuesta principal:

Para agregar a eso: el problema aquí es que en Linux uno puede eliminar archivos y directorios que están en uso, en Windows uno no puede. Es por eso que no funciona sin modificaciones. - Leon Timmermans