(Medio solucionado xD) [Ruby]Comprobar si un archivo está abierto por un proceso

Iniciado por Eleкtro, 1 Marzo 2012, 14:50 PM

0 Miembros y 1 Visitante están viendo este tema.

Eleкtro

Hola

Verán tengo un problema con el módulo FileUtils.move...

Si estos 2 archivos existen:

1º - C:\ABC.mp3
2º - D:\ABC.mp3


Imaginen que tenemos el 2º archivo abierto (Reproduciendose en winamp por ejemplo)
Ahora intentamos usar FileUtils.move para mover el 2º archivo, al directorio 1º. El archivo obviamente no se puede reemplazar, el FileUtils.move dará "error de acceso" pero a pesar de eso, FileUtils.move elimina el archivo 1º y desaparece!.

Y entonces nos queda esto:

1º - (NADA)
2º - D:\ABC.mp3



¿Se puede hacer algún tipo de "test" para que no elimine el archivo a reemplazar si da Errno::EACCES?
Lo que quiero decir, Es que primero se asegure de que la operación no va a dar error, Para que no elimine el archivo 1ª si el 2º no se puede mover.

Creo que por ahí leí algo como: FileUtils.test.move pero no estoy seguro...

También he visto    FileUtils::NoWrite, PEro no he visto ningún ejemplo de como usarlo, Ni tampoco se si sirve para lo que necesito.

Muchas gracias.




El code que tengo por si sirve para más información es este:

Código (ruby) [Seleccionar]
# -*- coding: UTF-8 -*-

# Mueve archivos desde un punto de origen hasta un punto de destino
# Pensado para usarlo como replazamiento del "SendTo" de Windows.
#
# (Requiere el uso de argumentos)


# Módulos

require "FileUtils"
require 'dl'

exit if Object.const_defined?(:Ocra)


# Variables constantes

BUTTONS_OKCANCEL = 1
BUTTONS_YESNO = 4
CLICKED_CANCEL = 2
CLICKED_YES = 6
CLICKED_NO = 7


# Métodos

def help()
print "\nSe requiere al menos 1 archivo de origen.\n\n\n"
print "Modo de empleo: \n\n"
print ' Mover.rb [Destino] [Archivo de origen 1] [Archivo de origen 2] [etc...]' + "\n\n\n"
print 'Ejemplo: (Mover tres archivos al directorio de destino "C:"' + "\n\n"
print ' Mover.rb "C:\" "D:\Archivo1.txt" "E:\Archivo2.jpg" "F:\Archivo3.mp3"' + "\n\n"
Process.exit
end

def message_box(txt, title='', buttons='')
   user32 = DL.dlopen('user32')
msgbox = DL::CFunc.new(user32['MessageBoxA'], DL::TYPE_LONG, 'MessageBox')
r, rs = msgbox.call([0, txt, title, 3].pack('L!ppL!').unpack('L!*'))
   return r
end

def force_move(source_file, dest_file)
 FileUtils.mv $archivo, ARGV[0]
 rescue Errno::EACCES
  response = message_box("El archivo esta en uso:\n" + $archivo  + "\n\n Reintentar?", "Reintentar?", BUTTONS_OKCANCEL)
if response == CLICKED_YES
      retry
  elsif response == CLICKED_CANCEL
      Process.exit
 end
end


# Control de errores

if ARGV.empty? == true
help()
elsif ARGV.length < 2
help()
elsif File.directory?(ARGV[0]) == false
print "\n El directorio de destino no existe: " + (ARGV[0]) + "\n"
Process.exit
end

for archivo in ARGV[1..ARGV.length].each
if File.exist?(archivo) == false
print "\n El archivo a mover no existe: " + archivo + "\n"
end

end


# Proceso

for $archivo in ARGV[1..ARGV.length].each

if File.exist?(ARGV[0] + "\\" + $archivo.split('\\').last)
response = message_box("Origen:\n" + $archivo + "\n\n Destino:\n " + ARGV[0] + "\\" + $archivo.split('\\').last + "\n\n El archivo de destino ya existe, Reemplazar archivo?", "Reemplazar archivo?", BUTTONS_YESNO)
if response == CLICKED_YES
  force_move($archivo, ARGV[0])
  elsif response == CLICKED_CANCEL
  Process.exit
end
else
force_move($archivo, ARGV[0])
end

end


# Fin
Process.exit








Eleкtro

#1
Me he mirado todo el módulo Kernel, FileUtils, Sysread, test, filestat, Process::Sys, IO, IO::WaitReadable, IO::WaitWritable, IOError... y el ftools

No encuentro la manera de como averiguar si un proceso (Cualquiera) tiene abierto un archivo.


¿alguna ayuda? :(

EDITO:
Joder, con lo fácil que es hacerlo en batch... Pero no quiero depender de eso.

Supongo que tendré que buscar hasta encontrar alguna gema parecida al "CMDOW" para windows xD








Eleкtro

#2
Al final he recurrido a un programa de terceros (CMDOW) para windows...

Posteo el code pa quien lo quiera probar (Aviso que soy novato, pueden sobrar varias cosas pero funciona bien), Me ha costado mucho esfuerzo xD

Ahora es cuando debería sonar una melodia de VICTORY! I'm great! ::)

salu2

Código (RUBY) [Seleccionar]
# Mueve archivos desde un punto de origen hasta un punto de destino
# Pensado para usarlo como replazamiento del "SendTo" de Windows.
#
# (Requiere el uso de argumentos)



# Modulos

require "FileUtils"
require 'dl'

exit if Object.const_defined?(:Ocra)



# Variables constantes

BUTTONS_OKCANCEL = 1
BUTTONS_YESNO = 4
CLICKED_CANCEL = 2
CLICKED_YES = 6
CLICKED_NO = 7



# Metodos

def help()
print "\nSe requiere al menos 1 archivo de origen.\n\n\n"
print "Modo de empleo: \n\n"
print ' Mover.rb [Destino] [Archivo de origen 1] [Archivo de origen 2] [etc...]' + "\n\n\n"
print ' Ejemplo: (Mover tres archivos al directorio de destino "C:"' + "\n\n"
print ' Mover.rb "C:\" "D:\Archivo1.txt" "E:\Archivo2.jpg" "F:\Archivo3.mp3"' + "\n\n"
Process.exit
end

def message_box(txt, title='', buttons='')
   user32 = DL.dlopen('user32')
msgbox = DL::CFunc.new(user32['MessageBoxA'], DL::TYPE_LONG, 'MessageBox')
r, rs = msgbox.call([0, txt, title, 3].pack('L!ppL!').unpack('L!*'))
   return r
end

def force_move(source_file, dest_file)

 rescue Errno::EACCES
  response = message_box("El archivo esta en uso:\n" + $archivo  + "\n\n Reintentar?", "Reintentar?", BUTTONS_OKCANCEL)
if response == CLICKED_YES
   Access($archivo, ARGV[0])
      retry
  elsif response == CLICKED_CANCEL
      Process.exit
 end
end

def reintentar(source_file, dest_file)
 response = message_box("El archivo esta en uso:\n" + $archivo  + "\n\n Reintentar?", "Reintentar?", BUTTONS_OKCANCEL)
if response == CLICKED_YES
     Access($archivo, ARGV[0])
  elsif response == CLICKED_NO
  nil
  elsif response == CLICKED_CANCEL
      Process.exit
end
end

def Access(source_file, dest_file)
ENV['tmp'] = $archivo.split('\\').last
'cheat environment_variables --add'
puts %x[cmdow.exe | Find "%tmp:~0,30%" >NUL]
response = $?.exitstatus
if response == 0
   reintentar($archivo, ARGV[0])
elsif response == 1
   FileUtils.mv $archivo, ARGV[0]
end
end



# Control de errores

if ARGV.empty? == true
help()
elsif ARGV.length < 2
help()
elsif File.directory?(ARGV[0]) == false
print "\n El directorio de destino no existe: " + (ARGV[0]) + "\n"
Process.exit
end

for archivo in ARGV[1..ARGV.length].each
if File.exist?(archivo) == false
print "\n El archivo a mover no existe: " + archivo + "\n"
end
end




# Proceso

for $archivo in ARGV[1..ARGV.length].each
if File.exist?(ARGV[0] + "\\" + $archivo.split('\\').last)
force_move($archivo, ARGV[0])
response = message_box("Origen:\n" + $archivo + "\n\n Destino:\n " + ARGV[0] + "\\" + $archivo.split('\\').last + "\n\n El archivo de destino ya existe, Reemplazar archivo?", "Reemplazar archivo?", BUTTONS_YESNO)
if response == CLICKED_YES
  Access($archivo, ARGV[0])
  elsif response == CLICKED_NO
  nil
  elsif response == CLICKED_CANCEL
  Process.exit
end
else
Access($archivo, ARGV[0])
end
end


# Fin
Process.exit



   
   


PD: El archivo de destino ya no se elimina al clickar "Reemplazar (SI)" porque primero comprueba si está en uso antes de usar el módulo FileUtils   :)