How to automatically find files of a specified type in the current directory or any specified sub-folders in Ruby? - ruby

I am using the following code to convert files from php to html. In order for it to work, I have to enter the name of each file on the second line.
p "convert files"
%w(file1 file2 file3).each do |name|
system %(php #{DIR}/#{name}.php > #{DIR2}/#{name}.htm)
end
Can someone tell me how to make it so it will automatically find any .php files in the main directory and look in any defined folder and their sub-folders for additional .php and save them in similar folder names?
For example:
file1.php -> file1.htm
about-us/file2.php -> about-us/file2.htm
contact-us/department/file3.php -> contact-us/department/file3.htm

The easiest way is to use Dir:
Dir.chdir('where_the_php_files_area')
Dir['**/*.php'].each do |php|
htm = 'where_the_html_files_should_go/' + php.sub(/\.php$/, '.htm')
system("php #{php} > #{htm}")
end
The ** pattern for Dir.glob (AKA Dir[]) matches directories recursively so Dir[**/*.php] will give you all the PHP files under the current directory.

Related

Why are Ruby's file related types string-based (stringly typed)?

e.g. Dir.entries returns an array of strings vs an array containing File or Dir instances.
Most methods on Dir and File types. The instances are aneamic in comparison.
There is no Dir#folders or Dir#files - instead I explicitly
loop over Dir.entries
build the path (File.expand_path) for
each item
check File.directory?
Simple use-cases like get all .svg files in this directory seem to require a number of hoops/loops/checks. Am I using Ruby wrong or does this facet of Ruby seem very un-ruby-ish?
Depending on your needs, File or Dir might do just fine.
When you need to chain commands and (rightfully) think it feels un-ruby-ish to only use class methods with string parameters, you can use Pathname. It is a standard library.
Examples
Dirs and Files
require 'pathname'
my_folder = Pathname.new('./')
dirs, files = my_folder.children.partition(&:directory?)
# dirs is now an Array of Pathnames pointing to subdirectories of my_folder
# files is now an Array of Pathnames pointing to files inside my_folder
All .svg files
If for some reason there might be folders with .svg extension, you can just filter the pathnames returned by Pathname.glob :
svg_files = Pathname.glob("folder/", "*.svg").select(&:file?)
If you want a specific syntax :
class Pathname
def files
children.select(&:file?)
end
end
aDir = Pathname.new('folder/')
p aDir.files.find_all{ |f| f.extname == '.svg' }
Iterating the Directory tree
Pathname#find will help.
Until you open the file it is just a path (string).
To open all .svg files
svgs = Dir.glob(File.join('/path/to/dir', '*.svg'))
On windows case doesn't matter in file paths, but in all unixoid systems (Linux, MacOS...) file.svg is different from file.SVG
To get all .svg files and.SVG files you need File::FNM_CASEFOLD flag.
If you want to get .svg files recursively, you need **/*.svg
svgs = Dir.glob('/path/to/dir/**/*.svg', File::FNM_CASEFOLD)
If you expect directories ending in.svg then filter them out
svgs.reject! { |path| File.directory?(path) }

Moving files with specific file name & extension

I'd like to create a batch file under windows to move files with specific file names. I'd like to move all the files with txt extension and filename starting with "HH", and moving them only from root, sub directories excluded. And if a file with the same name is already exist in the destination directory I'd like to auto rename files instead of overwriting. Is it possible to do?
You can simply use:
move c:\HH*.txt destination_directory

Ruby - Why does Dir.foreach pass `.` and `..` as the first two parameters?

In an empty directory, the following code
Dir.foreach("./") do |file|
puts file
end
returns
.
..
In my understanding . refers to the working directory and .. refers to the parent directory; why does foreach seem to treat them as files within the working directory?
Because they are files within the working directory. The . and .. directories are not magical; they appear the same way any subdirectory does, as entries in the directory. Every directory on a UNIX-type file system has actual directory entries named . and ... So if you don't want to include them when processing a directory, you need to exclude them yourself.

How to check the content of each .txt file in a folder with Ruby

I have a folder that contains files. I was wondering how I can chech every .txt file in the folder if it contains the word "BREAK". I know it must be very easy but I kinda miss the way of getting it done.
This is what I've tried so far
Dir.glob('/path/to/dir/*.txt') do |txt_file|
# And here I need a method that opens the 'txt_file'
# and checks if it contains "BREAK"
end
The below would return an array of files containing "BREAK"
files = Dir.glob('/path/to/dir/*.txt').select do |txt_file|
File.read(txt_file).include? "BREAK"
end

Recursively find folder names only (not files)

Is it possible to display the folder names (only) recursively. I know, to display the files from the specific folder using the following command.
Dir.glob("/home/test/**/*.pdf")
or
Dir['/home/test/**/*.*']
But, i need to display folder name only.
you put a slash, like this
Dir["**/"].each {|x| puts x}

Resources