Undo capitalization of directories under root Dropbox directory - ruby

I am using Dropbox Ruby API. When I receive the "path" of the directories on the Dropbox server via its API, the directory paths are capitalized if they are directly under the Dropbox root directory, irrespective of whether the corresponding directory on the local computer is capitalized. Given the information on the Dropbox server, how can I achieve the corresponding path on the local computer with the correct alphabet case? Simply applying downcase to the given path does not work because some directories on the local computer might actually be capitalized.

You could try a case insensitive search for the file in question or just use a case insensitive regex in general. Just be sure to match the full file name unlike the example below:
require 'find'
Find.find('.') do |path|
if path =~ /file_name/i
p path
end
end

Related

Ruby - Getting the UNC Path of a local file

Is it possible in Ruby running on Windows to resolve a local file to its UNC path.
For example: D:\hello.jpg should resolve to \\server01\DShare\hello.jpg
Drive letter D is shared as DShare on server01. I also want this to work for any given drive letter that is shared.
Similar question was asked in Python: Python 2: Get network share path from drive letter
If possible, I'd prefer for it to be achieved without installing additional Gems.
This code almost does it, but I want to use the Share name rather than the admin share $
def File.to_unc( path, server="localhost", share=nil )
parts = path.split(File::SEPARATOR)
parts.shift while parts.first.empty?
if share
parts.unshift share
else
# Assumes the drive will always be a single letter up front
parts[0] = "#{parts[0][0,1]}$"
end
parts.unshift server
"\\\\#{parts.join('\\')}"
end

How to get filepaths that match a glob without having them on the filesystem

I have a list of filepaths relative to a root directory, and am trying to determine which would be matched by a glob pattern. I'm trying to get the same results that I would get if all the files were on my filesystem and I ran Dir.glob(<my_glob_pattern>) from the root diectory.
If this is the list of filepaths:
foo/index.md
foo/bar/index.md
foo/bar/baz/index.md
foo/bar/baz/qux/index.md
and this is the glob pattern:
foo/bar/*.md
If the files existed on my filesystem, Dir.glob('foo/bar/*.md') would return only foo/bar/index.md.
The glob docs mention fnmatch, and I tried using it but found that the pattern foo/bar/*.md was matching .md files in any number of nested subdirectories, similar to what Dir.glob('foo/bar/**/*.md') would, not just the direct children of the foo/bar directory:
my_glob = 'foo/bar/*.md'
filepaths = [
'foo/index.md',
'foo/bar/index.md',
'foo/bar/baz/index.md',
'foo/bar/baz/qux/index.md',
]
# Using the provided filepaths
filepaths_that_match_pattern = filepaths.select{|path| File.fnmatch?(my_glob, path)}.sort
# If the filepaths actually existed on my filesystem
filepaths_found_by_glob = Dir.glob(my_glob).sort
raise Exception.new("They don't match!") unless filepaths_that_match_pattern == filepaths_found_by_glob
I [incorrectly] expected the above code to work, but filepaths_found_by_glob only contains the direct children, while filepaths_that_match_pattern contains all the nested children too.
How can I get the same results as Dir.glob without having the file paths on my filesystem?
You can use the flag File::FNM_PATHNAME while calling File.fnmatch function. So your function call would look like this - File.fnmatch(pattern, path, File::FNM_PATHNAME)
You can see examples related to its usage here: https://apidock.com/ruby/File/fnmatch/class
Don't use File.fnmatch, instead use Pathname.fnmatch:
require 'pathname'
PATTERN = 'foo/bar/*.md'
%w[
foo/index.md
foo/bar/index.md
foo/bar/baz/index.md
foo/bar/baz/qux/index.md
].each do |p|
puts 'path: %-24s %s' % [
p,
Pathname.new(p).fnmatch(PATTERN) ? 'matches' : 'does not match'
]
end
# >> path: foo/index.md does not match
# >> path: foo/bar/index.md matches
# >> path: foo/bar/baz/index.md matches
# >> path: foo/bar/baz/qux/index.md matches
File assumes the existence of files or paths on the drive whereas Pathname:
Pathname represents the name of a file or directory on the filesystem, but not the file itself.
Also, regarding using Dir.glob: Be careful using it. It immediately attempts to find every file or path on the drive that matches and returns the hits. On a big or slow drive, or with a pattern that isn't written well, such as when debugging or testing, your code can be tied up for a long time or make Ruby or the machine Ruby's running on go to a crawl, and it only gets worse if you're checking a shared or remote drive. As an example of what can happen, try the following at your command-line, but be prepared to hit Cntrl+C to regain control:
ls /**/*
Instead, I recommend using the Find class in the Standard Library as it will iterate over the matches. See that documentation for examples.

Get current path with äöüè in name (__FILE__)

Using Windows, I've experienced a slight annoyance when using __FILE__ to get the current location of a file or the absolute path of another file with
File.expand_path("lib/other", File.dirname(__FILE__))
This doesn't work though if the folder has characters like äöüè and similar. This get's especially annoying if the windows username of a client contains such a character and my script necessarily lives inside the %appdata% folder.
To demonstrate my problem, C:\äüé\test.rb contains only
puts __FILE__
Running it:
> ruby C:\äüé\test.rb
C:/"?'/test.rb
Is there a reliable way to get the current file path?

If I have the name of a file, how do I search a folder for a file that contains that filename?

I have an image with the filename media_httpfarm3static_mAyIi.jpg.
I would like to search the parent folder and all subfolders of that parent folder for a file that contains that name - it doesn't have to be the EXACT name, but must contain that string.
E.g. this file should be returned: 11605730-media_httpfarm3static_mAyIi.jpg
So this is a 2-part question:
How do I achieve the above?
Once I have the file, how do I return the path for that file?
Use Dir::[] and File::absolute_path:
partial_name = "media_httpfarm3static_mAyIi.jpg"
Dir["../**/*#{partial_name}"].each do |filename|
puts File.absolute_path(filename)
end
This uses the glob "../**/*media_httpfarm3static_mAyIi.jpg" (go up one directory, then search all sub directories (recursively), for any file ending in the partial string "media_httpfarm3static_mAyIi.jpg". The relative paths are then returned in an Array.
You can use Array#each, Array#map, etc. to convert this into what you need. To convert a relative path, into an absolute path, just pass it to File::absolute_path.
Once you have the absolute path, you can use it to open the file, read the file, etc.
On File Paths
The glob "../**/*media_httpfarm3static_mAyIi.jpg" is relative to the current working directory. Normally, this is the directory from which the program was run. Not the directory of the source file. This can change using various utilities to change it.
To always use a glob relative to the source code file, try:
Dir[File.expand_path('../**/*#{partial_name}', __FILE__)]
You can also use:
Dir[File.join(__dir__, "..", "**", "*#{partial_name}")]
Note: __dir__ was added in Ruby 2.0. For older versions of ruby use File.dirname(__FILE__)
In the first code sample File::absolute_path was used. In the last sample File::expand_path is used. In most situations these can be used interchangeably. There is a minor difference, per the documentations:
File::absolute_path
Converts a pathname to an absolute pathname. Relative paths are
referenced from the current working directory of the process unless
dir_string is given, in which case it will be used as the starting
point. If the given pathname starts with a “~” it is NOT expanded, it
is treated as a normal directory name.
File::expand_path
Converts a pathname to an absolute pathname. Relative paths are
referenced from the current working directory of the process unless
dir_string is given, in which case it will be used as the starting
point. The given pathname may start with a “~”, which expands to the
process owner’s home directory (the environment variable HOME must be
set correctly). “~user” expands to the named user’s home directory.

RUBYLIB Environment Path

So currently I have included the following in my .bashrc file.
export RUBYLIB=/home/git/project/app/helpers
I am trying to run rspec with a spec that has
require 'output_helper'
This file is in the helpers directory. My question is that when I change the export line to:
export RUBYLIB=/home/git/project/
It no longer finds the helper file. I thought that ruby should search the entire path I supply, and not just the outermost directory supplied? Is this the correct way to think about it? And if not, how can I make it so RUBY will search through all subdirectories and their subdirectories, etc?
Thanks,
Robin
Similar to PATH, you need to explicitly name the directory under which to look for libraries. However, this will not include any child directories within, so you will need to list any child sub-directories as well, delimiting them with a colon.
For example:
export RUBYLIB=/home/git/project:/home/git/project/app/helpers
As buruzaemon mentions, Ruby does not search subdirectories, so you need to include all the directories you want in your search path. However, what you probably want to do is:
require 'app/helpers/output_helper'
This way you aren't depending on the RUBYLIB environment variable being set a certain way. When you're deploying code to production, or collaborating with others, these little dependencies can make for annoying debugging sessions.
Also as a side note, you can specify . as a search path, rather than using machine-specific absolute paths.

Resources