Copy folders which starts with character in Ruby - ruby

How to copy folders which starts with only letters not with numbers. I am trying something like
Dir.glob("folderpath/[a-z]").each do|f|
FileUtils.cp_r f, "dest"
end

Dir glob expects to match the whole name (unlike regex).
So, you will need to do:
Dir.glob("folderpath/[a-z]*").each{|f|FileUtils.cp_r(f,"dest")}
(use the do syntax if you prefer)
see https://ruby-doc.org/core-3.0.0/Dir.html#method-c-glob
Note that if the underlying filesystem is case insensitive, then matching is made case insensitive although the pattern is lower case.
For instance, on a mac it matches README and etc
If you prefer regex, or need more complex test, you can use:
Dir.foreach("folderpath").
select{|n|n.match(/^[a-z]/)}.
map{|n|File.join("folderpath",n)}.
each{|f|FileUtils.cp_r(f,"dest")}
Here we use a regex. Note it is case sensitive even if the underlying filesystem is case insensitive. Add i after the last / to make case insensitive if needed. The map is here to add the folder path so that you can add the cp_r

Related

Glob string pattern for one or more files

I need a pattern for one or more files, name of each will be known before the matching occurs (but I do not know what they are right now).
For example, one occurence could be two files: A.lkml and B.lkml, and another could be three: CDFDFDSADF.lkml, SD.lkml and R4545452.lkml. The filenames will be passed as a single argument with single space as separator (So for example 1, will see A.lkml B.lkml).
What I can be sure of:
all files end with .lkml
for each matching, I need to add a manifest.lkml into the list. For example, in example 1, the list should contain 3 instead of 2 filenames, A.lkml, B.lkml and manifest.lkml
What puzzles me is that glob pattern matching doesn't seem to be able to do logic "OR". I have tried to use ",", "|" to no avail. In my experiments I fixed the filenames but in reality they change each time.
Update: I think brace expression such as {a.lkml,manifest.lkml} should work. Somehow it doesn't pass.

Ruby regexp /(\/.*?(?=\/|$)){2}/

My regexp behaves just like I want it to on http://regexr.com, but not like I want it in irb.
I'm trying to make a regular expression that will match the following:
A forward slash,
then 2 * any number of random characters (i.e. `.*`),
up to but not including another /
OR the end of the string (whichever comes first)
I'm sorry as that was probably unclear, but it's my best attempt at an English translation.
Here's my current attempt and hopefully that will give you a better idea of what I'm trying to do:
/(\/.*?(?=\/|$)){2}/
The usage scenario is I want to be able to take a path like /foo/bar/baz/bin/bash and shorten it to the level I'm at in the filesystem, in this case the second level (/foo/bar). I'm trying to do this using the command path.scan(-regex-).shift.
The usage scenario is I want to be able to take a path like /foo/bar/baz/bin/bash and shorten it to the level I'm at in the filesystem, in this case the second level (/foo/bar)
Ruby already has a class for handling paths, Pathname. You can use Pathname#relative_path_from to do what you want.
require 'pathname'
path = Pathname.new("/foo/bar/baz/bin/bash")
# Normally you'd use Pathname.getwd
cwd = Pathname.new("/foo/bar")
# baz/bin/bash
puts path.relative_path_from(cwd)
Regexes just invite problems, like assuming the path separator is /, not honoring escapes, and not dealing with extra /. For example, "//foo/bar//b\\/az/bin/bash". // is particularly common in code which joins together directories using paths.join("/") or "#{dir}/#{file}.
For completeness, the general way you match a single piece of a path is this.
%r{^(/[^/]+)}
That's the beginning of the string, a /, then 1 or more characters which are not /. Using [^/]+ means you don't have to try and match an optional / or end of string, a very useful technique. Using %r{} means less leaning toothpicks.
But this is only applicable to a canonicalized path. It will fail on //foo//b\\/ar/. You can try to fix up the regex to deal with that, or do your own canonicalization, but just use Pathname.

File.directory? returns false because ENV["HOME"] contains path with Russian words

File.directory?(ENV["HOME"])
returns false because ENV["HOME"] contains path with Russian words, like:
c:/Users/Администратор
How do I solve it?
You seem to be on Windows. Windows has the oddity, that upper- and lowercase file names are not distinguished (i.e. Windows remembers the case of the letters, when the entry is created, but it ignores case, when a filename is used). Ruby tries to mimic this, but I don't know whether it is able to to this "case-insensitivity" with cyrillic characters. Could it be that the directory had been created in a different spelling (with regard to upper/lower case), than it is stored in the ENV hash?
I would proceed as follows: From an irb shell, do a
Dir['c:/Users']
You should see the entries in the "correct" spelling. Does it exactly match the content of ENV['HOME']? If you use copy and paste from this output, and ask (again in the irb shell) for File.directory?('....'), does it evaluate to true then?

Modify regex to match expanded folder struction

I have a regex that I am using to search for files .ipa files in my '_inbox' folder. It works for files that are directly under that folder. But now I need to modify it to find files in subfolders.
current regex
%r{_inbox/[^/]+.ipa}i
matches
'_inbox/NewApplication.ipa'
does not match
'_inbox/Test/1/NewApplication.ipa'
I don't have the rep required to comment so I'll do my best to answer without. I think ruby supports lookahead, if it doesn't, this answer is partially invalid.
I think this regex should cover what you need, or at least be a good starting point:
_inbox/[^/](?!//)[\w\d\_\-\./]+?\.ipa
This RegEx will match a file path starting with _inbox/, unless there is another slash afterwards.
Next, it uses a negative lookahead (?!//) to ensure that the rest of the subject string doesn't contain two consecutive slashes. If it doesn't contain that, it makes sure that the rest of the string is made entirely of upper/lower case letters: \w, digits: \d, underscores, dashes, dots or forward slashes: \_\-\./. Finally, it checks that the path ends with the file extension: \.ipa.
Hope this helps.
You can match subfolders with (?:[^/]+/)*:
%r{_inbox/(?:[^/]+/)*[^/]+\.ipa}i
Please see demo.
Also, you'd better escape the dot to match the literal dot.
Why use a regex rather than Dir#glob? If the current directory contains the "_inbox" subdirectory, the following will return the array you want:
Dir.glob(File.join("**","_inbox","**","*.ipa"))

ParseGlob: What is the pattern to parse all templates recursively within a directory?

Template.ParseGlob("*.html") //fetches all html files from current directory.
Template.ParseGlob("**/*.html") //Seems to only fetch at one level depth
Im not looking for a "Walk" solution. Just want to know if this is possible. I don't quite understand what "pattern" this expects. if i can get an explanation about the pattern used by ParseGlob that would be great too.
The code text/template/helper.go mentions
// The pattern is processed by filepath.Glob and must match at least one file.
filepath.Glob() says that "the syntax of patterns is the same as in Match"
Match returns true if name matches the shell file name pattern.
The implementation of Match() doesn't seem to treat '**' differently, and only consider '*' as matching any sequence of non-Separator characters.
That would mean '**' is equivalent to '*', which in turn would explain why the match works at one level depth only.
So, since the ParseGlob can't load templates recursively we have to use path/filepath.Walk function. But this way gives more opportunities.
https://gist.github.com/logrusorgru/abd846adb521a6fb39c7405f32fec0cf

Resources