is there to invoke 'previous' in Find? (or refresh the current path?)

D

dtown22

I am writing a small script which recursively goes down a dir
hierarchy, and when it reaches a set of files, it applies a 3rd party
application which modifies those files, and prepends the name with
"Mod-".

So for example, if i had a directory with only 1 file: C:\myDir
\myFile.txt, and I ran the app, I would end up with the following
files in c:\myDir

myFile.txt
Mod-myFile.txt

Basically, what i want to do is traverse down the hierarchy, when i
reach a set of files, call the app on that directory, then delete the
original, and rename the new file so that the "Mod-" is removed.
Unfortunately, the Find function doesnt see the newly created file,
and thus i cant delete & rename. My code looks something like this:

Find.find(startingDir) do |path|
if File.directory?(path)
next
else
system("myapp #{path}")
puts path
if File.basename(path) =~ /^Mod-/
if File.exists?(path.sub('Mod-', ''))
File.delete(path.sub('Mod-', ''))
end
File.rename(path, path.sub('Mod-', ''))
end
end
end

I was wondering if there was a way to reset the path one level up
(i.e. where "puts path" is above), that way the current directory
would be refreshed, and the new files would be recognized.

thanks!
 
L

Logan Capaldo


This is unacceptable. One does not "bump" a mailing list, especially
if one's original mail was sent less that 24 hours ago. Sending a
wasteful message with no content will not incline anyone to answer
your question more quickly. Please do not do it again.
 
D

dtown22

sorry for that...generally i post on forums, and i have never felt
that bumping a thread on a forum was a no no...but i can understand
why it would be so on a mailing list.

i am just a bit eager to solve this problem...
 
D

Daniel Berger

I am writing a small script which recursively goes down a dir
hierarchy, and when it reaches a set of files, it applies a 3rd party
application which modifies those files, and prepends the name with
"Mod-".

So for example, if i had a directory with only 1 file: C:\myDir
\myFile.txt, and I ran the app, I would end up with the following
files in c:\myDir

myFile.txt
Mod-myFile.txt

Basically, what i want to do is traverse down the hierarchy, when i
reach a set of files, call the app on that directory, then delete the
original, and rename the new file so that the "Mod-" is removed.
Unfortunately, the Find function doesnt see the newly created file,
and thus i cant delete & rename. My code looks something like this:

Find.find(startingDir) do |path|
if File.directory?(path)
next
else
system("myapp #{path}")
puts path
if File.basename(path) =~ /^Mod-/
if File.exists?(path.sub('Mod-', ''))
File.delete(path.sub('Mod-', ''))
end
File.rename(path, path.sub('Mod-', ''))
end
end
end

I was wondering if there was a way to reset the path one level up
(i.e. where "puts path" is above), that way the current directory
would be refreshed, and the new files would be recognized.

I don't think so. You'll probably have to use Dir.glob, keep a
separate array of paths already visited and manually rewind back to
your queue.

You post does give me some devilish ideas for my file-find library,
and made me reconsider the implementation in general. I think I should
use Dir.new (instead of Dir.foreach) and iterate over the file list
using the returned handle. That way I can use Dir#rewind, and "fast
forward" to a given point in an array of already visited paths. You
may want to consider that approach as well.

I'll also post what I come up with for file-find. :)

Regards,

Dan
 
D

Daniel Berger

I don't think so. You'll probably have to use Dir.glob, keep a
separate array of paths already visited and manually rewind back to
your queue.

You post does give me some devilish ideas for my file-find library

<snip>

Ok, here's what I came up with. First, I added a Rule#previous method,
which shows you the file you iterated over previously (or nil, if it's
the first match). With this in place you can do something like this:

require 'file/find'

rule = File::Find.new(
:name => "z*.h",
:path => "/my/include/sys"
)

rule.find{ |file|
if file == 'zone.h'
# Rename zone.h
rule.rewind(rule.previous)
else
puts file
end
}

The rewind code isn't the zippiest thing, but it works.

How does that look?

Regards,

Dan
 
D

dtown22

Hi Dan,

I'm guessing 'file/find' is a gem of yours? I wasnt able to find it
using the gem command.
 
A

ara.t.howard

myFile.txt
Mod-myFile.txt

Basically, what i want to do is traverse down the hierarchy, when i
reach a set of files, call the app on that directory, then delete the
original, and rename the new file so that the "Mod-" is removed.
Unfortunately, the Find function doesnt see the newly created file,
and thus i cant delete & rename. My code looks something like this:

Find.find(startingDir) do |path|
if File.directory?(path)
next
else
system("myapp #{path}")
puts path
if File.basename(path) =~ /^Mod-/
if File.exists?(path.sub('Mod-', ''))
File.delete(path.sub('Mod-', ''))
end
File.rename(path, path.sub('Mod-', ''))
end
end
end

this makes no sense at all - you *know* that the file is created -
you don't *care* if find sees it. all you need to do is

require 'fileutils'

Dir.glob('**/**') do |src|
next if test ?d, src

dst = "Mod-#{ src }"

cmd = "app #{ src }"
system cmd

abort "<#{ cmd }> failed with <#{ $?.inspect }>" unless
$?.exitstatus.zero? and test ?e, dst

FileUtils.rm_f src
FileUtils.mv dst, src
end

or am i missing something here?

cheers.

a @ http://drawohara.com/
 
D

dtown22

Hi ara,

I don't necessarily know that the file is created, since I provide the
directory containing the files to the 3rd party app, and it make not
have successfully modified all the of the files.

My thought process is something like this:

1. traverse down the directory tree, when i reach a specified file
type, i know i have found one of the many directories which contain
the files i want to modify,
2. pass the directory to the 3rd party app, and it does its thing, and
hopefully the files are modified correctly (even if some or not, i do
not want to stop the script, i would like it to continue on, modifying
and renaming
3. refresh the current directory, go through each of the files, if the
original file exists, and the modified one, delete the original, and
rename the modified.
4. back to step 1

Hope this clears things up a bit
 
A

ara.t.howard

Hi ara,

I don't necessarily know that the file is created, since I provide the
directory containing the files to the 3rd party app, and it make not
have successfully modified all the of the files.

sure but if

- it modified correctly you can do the move yourself
- it did not then simply do nothing or blow up

either way it does not seem essential that find picks this file up
since you are clobber a file it already found right?

My thought process is something like this:

1. traverse down the directory tree, when i reach a specified file
type, i know i have found one of the many directories which contain
the files i want to modify,
2. pass the directory to the 3rd party app, and it does its thing, and
hopefully the files are modified correctly (even if some or not, i do
not want to stop the script, i would like it to continue on, modifying
and renaming
3. refresh the current directory, go through each of the files, if the
original file exists, and the modified one, delete the original, and
rename the modified.
4. back to step 1

Hope this clears things up a bit

hmmm i'm not following, you say 'pass the directory to the 3rd party
app' but your code reads

Find.find(startingDir) do |path|
if File.directory?(path)
next
else
system("myapp #{path}")
puts path
if File.basename(path) =~ /^Mod-/
if File.exists?(path.sub('Mod-', ''))
File.delete(path.sub('Mod-', ''))
end
File.rename(path, path.sub('Mod-', ''))
end
end
end


so you skip over all directories and only process files? let's
assume the app actually does process directories at a time. then the
problem is pretty each

def has_the_right_kind_of_files entries
entries.detect{|entry| entry =~ %r/whatever/}
end

def scour pathname = '.'
if test ?d, pathname
glob = File.join pathname, '*'
entries = Dir.glob glob

if has_the_right_kind_files(entries)
system "app #{ pathname }"
entries = Dir.glob glob
end

entries.each{|entry| scour entry}
else
dirname, basename = File.split pathname
match, src = %r/^Mod-(.*)$/.match(basename).to_a
if match
FileUtils.mv pathname, File.join(dirname, src)
end
end
end


not that the above code will work first shot - but you get the idea:
simply process the directories *before* recursing into them.

cheers.


a @ http://drawohara.com/
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,579
Members
45,053
Latest member
BrodieSola

Latest Threads

Top