I'd like to grab all the files in a particular directory, and then apply a gsub(/abc/,'z') to all the filenames and essentially resave the files under the new filenames, how do I do that?
I've been looking at File but I don't seem to have any of the parameters that it requires, aka the filename, etc.
M
File.rename(from, to) along with Dir.entries (or Dir.foreach)?
Dave's answer is right on. Here's an example:
Dir.glob("*.rb").each do |fname|
File.rename(fname, fname.gsub(/\.rb/,".rbb"))
end
Dir.glob allows you to select files based on some given criteria, but like Dave says, you could also use Dir.entriesor Dir.foreach
Related
A lot of people send me their invoices and they are almost always .pdf files. I have a limited attention span and so have written some ruby code to save me having to look at them. It would help if my bit of Ruby code would look into a folder and, if there was an invoice there, return the name of the file and its path. The thing is that the people who send me their invoices are very annoying and name their files in the worst way. For example, one of them has given me an invoice called "Invoice_Cost_Centre_6454537.pdf". I can't be expected to remember that sort of name. However they are always (almost) .pdfs.
I was taking to Ruby about it and she said this,
File.exist?('test\Invoice_Cost_Centre_61356.pdf')
#=> true
File.exists?('test\*.pdf')
#=> false
I have had a look at the docs for the File class and thought that File.fnmatch?(pattern, path) might be a solution but I couldn't get it to work.
I would appreciate any help. I'm fairly new to Ruby so please keep your sentences short.
File.exists? checks if a file with that path exists verbatim.
File.fnmatch? checks if a path matches a given pattern, but doesn't actually look up that path.
Instead you could Dir['test/*.pdf'].empty?
The method Dir.glob is used for achieving file names that match a certain pattern, but its argument has a Unix-like syntax (e.g., using *, ** as wild cards in a particular way, etc.). Instead, I want to use Ruby (Onigmo) regex for the matching pattern to do the same thing (using its wildcards, quantifiers, anchors, escaped characters, etc). What is the best way to do this?
One simple way that comes to mind is to use Dir.glob to get the list of all existing files in all directories, and filtering them using the regex, but that does not look efficient. Or, is it? Is there a better way?
You could try the Find module in Ruby's standard library.
require 'find'
Find.find(path).grep(/regex/)
The find method returns every path that exists within the path you provide as an argument recursively, pretty much like what you mentioned with Dir.glob. You can then use the built-in grep method to filter the results with a regex.
This may not be the most efficient method though, since Dir.glob is written in C while the Find module is written in Ruby. I did a test on my home directory and it took Find a little longer to get the result than Dir.glob, but you can also use the Find module's prune method in order to not descend into particular folders, which could help make things more efficient using Find.
I am currently writing a Ruby script to manage my dotfiles. I want to keep a list of the tracked dotfiles, and am not quite sure how to go about this.
The thing is that the list would be so simple, e.g
tmux.conf
zshrc
vimrc
so I feel using yml, xml or various other formats would be overkill. I do not need to store indexes, paths, order or anything of the sort. However, storing the filesnames in a file separated by newlines or commas still feel kind of "dumb". How should I go about this?
UPDATE
It seems like my question wasn't clear enough. I know how to write to and read from files and DB using Ruby. My question was meant to be something like What is the best practice for storing single-values in a file?
Should I use a known file format like YAML or XML, or what would you choose?
through this you can get all file name in an array now you can write them to file
file_names = Dir.entries(".").select {|f| !File.directory? f}
file = File.open(local_filename, 'w')
file_names.each do |name|
file.write(name + "\n")
end
I'd simply go with new-line separated values or storing it inside the script. It's definitely not dumb, it's just the way you do things like that.
Find.find("d") {|path| puts path}
I want to exclude certain type of files, say *.gif and directories.
PS: I can always add code inside my block to check for the file name and directory type, but I want find itself to filter files for me.
I don't think you can tell find to do that.You could try using Dir#[], which accepts file globs. If you are looking for particular types of files, or files that can be filtered with the file glob pattern language, it may be a better fit.
eg
Dir["dir/**/*.{xml,png,css,html}"]
would find all the xml, png, css, and html files under the directory d.
Check out the docs for more info.
You can't make find do it, but Find may help: in the block, you need to check whether the current path is one of those you'd like to exclude or not; if so, then call Find#prune. This seems to be the standard idiom when using Find.
If you decide to use Dir#[] instead, you may call reject on its result, passing a block to exclude certain types of files. However, note that, as far as I understand, Dir#[] reads all the contents of your d directory before you can filter, while Find#prune guarantees not to read the contents of pruned subdirectories if you call it within the block passed to Find#find.
I'm using the split linux command to split huge xml files into node-sized ones. The problem is now I have directory with hundreds of thousands of files.
I want a way to get a file from the directory (to pass to another process for import into our database) without needing to list everything in it. Is this how Dir.foreach already works? Any other ideas?
You can use Dir.glob to find the files you need. More details here, but basically, you pass it a pattern like Dir.glob 'dir/*.rb' and get back filenames matching that pattern. I assume it's done in a reasonably good way, but it will depend on your platform and implementation.
As to Dir.foreach, this should be efficient too - the concern would be if it has to process the entire directory for every pass around the loop. But that would be awful implementation, and is not the case.