I'd like to do the following in raku on windows
raku -n -e ".say if /mydatabegin/;" *.file
Failed to open file C:\..\*.file: Invalid argument
The glob isn't interpreted as a glob. I assume that's because windows requires your programs to do the globbing yourself? So is there a pre-processing directive or function or even a switch I might have missed or redirect or something that allows the glob to be expanded while keeping the simplicity of the -n (or -p) and -e switches?
Obviously, I can change it to a full program by removing the -n (or -p), just using -e to specify a main, and loop on the glob results. But I really like -n.
PS. I'm literally just learning raku, and was surprised this didn't work out of the box. So examples of full programs with easy syntax work also. But I really like -n..
Edit: re @chenyf
raku -e ".say for $*ARGFILES" *.file
Same error. Related:
raku -e ".say for $*ARGFILES.lines" *.file
Same error.
raku -e "use IO::Glob; .say for glob('*.file')"
Worked as expected! Expanding:
raku -e "use IO::Glob; .say for glob('*.file').lines"
No such method 'lines' for invocant of type 'IO::Glob'
Getting closer - perhaps expanding on this is a good enough workaround. But returning to one line glory attempts:
raku -e "use IO::Glob; .say for glob($*ARGFILES)" test.file
Cannot resolve caller glob(IO::ArgFiles:D); none of these signatures match.
Ok - let's retreat back to the safety of strings:
raku -e "use IO::Glob; .say for glob($*ARGFILES.Str)" test.file
Yes! SO..:
raku -e "use IO::Glob; .say for glob($*ARGFILES.Str).lines" test.file
No such method 'lines' for invocant of type 'IO::Glob'
I clearly need to read more of the manual. But let's retreat a little and see if my use case works:
raku -e "use IO::Glob; .say for glob($*ARGFILES.Str)" *.file
Failed to open file C:\..\*.file: Invalid argument
The same error I started off with. Could this just be a raku on windows error?
Edit:
raku -MIO::Glob -e "my @files = (map { glob($_).dir }, @*ARGS).flat; for @files -> $file { say $_ for $file.lines }" *file *file2 *5
I have three sets of files. I can almost live with this solution - except for some reason the lines are being printed with "s
Any ideas on shortening, and getting rid of the quotes?
EDIT Working around the auto-globbing of the $*ARGFILES variable:
raku -MIO::Glob -n -e "BEGIN { @*ARGS = (map { glob($_) }, @*ARGS).flat }; .say" *.file *.file2
This has the advantage of still looking like the original one liner; it uses -n! It just had to do the globbing that seems to be a bug when $*ARGFILES is created.
raku -MIO::Glob -e "BEGIN { @*ARGS = (map { glob($_) }, @*ARGS).flat }; .say for $*ARGFILES.lines" *.file *.file2
Converting to $*ARGFILES.lines above shows that $*ARGFILES gets its values from @*ARGS dynamically.
EDIT
lastly, it turns out the glob function doesn't work with directories, at least on windows (the documentation has an example that simply doesn't work).
#Example from https://github.com/zostay/raku-IO-Glob
for glob("src/core/*.pm") -> $file { say ~$file }
#mine that doesn't work
raku -MIO::Glob -e "for glob('..\*.file') -> $file { say ~$file }"
#mine that does work.
raku -MIO::Glob -e "for glob('*.file').dir('..') -> $file { say ~$file }"
#And therefore the final modification of the script above:
raku -MIO::Glob -e "BEGIN { @*ARGS = (map { glob(.IO.basename).dir(.IO.dirname) }, @*ARGS).flat }; .say for $*ARGFILES.lines" ..\*.file
My rudimentary understanding of file-globbing is that the shell handles that--and since it seems that you're on Windows, all bets may be off. The only exception may be if you're using WSL
Windows-Subsystem-for-Linux, which should give you a more Unix/Linux-like experience:
https://learn.microsoft.com/en-us/windows/wsl/about
According to the Microsoft document below Windows has two built-in shells, CMD.exe and Powershell (I believe the WSL shell above is optional):
"Command Shell Overview"
"Windows has two command shells: The Command shell and PowerShell. Each shell is a software program that provides direct communication between you and the operating system or application, providing an environment to automate IT operations."
https://learn.microsoft.com/en-us/windows-server/administration/windows-commands/windows-commands
Below is what works on a fairly old bash/MacOS
system.
With the -ne
(non-autoprinting) command line flag:
raku -ne 'print $_ ~ "\n";'
raku -ne 'say $_ ;'
raku -ne '.say;'
With the -pe
(autoprinting) command line flag:
raku -pe 'print "";'
raku -pe ''
I literally just printed the contents of five (5) *.txt
files using the commands above. The -e
flag always ends your command-line flag cluster, but can be combined (see the -M
flag below for an exception).
Now because you're on Windows, you may have to swap ""
double-quotes with ''
single-quotes, (and vice versa!). But hopefully that gets you started. [Any further problems and you may have to specify the full-path to your Rakudo executible].
If you'd like Raku to handle the directory-munging for you, there's Raku's dir()
command, which can be used in conjunction with its :test
adverb (parameter). Compare below when in the afore-mentioned directory with five (5) *.txt
text files, (remove .elems
calls to print actual text):
raku -e '.lines.elems.say for dir(test => / \.txt $ /);'
14
16
34
1
16
VERSUS:
raku -e '.lines.elems.say for $*ARGFILES;' *.txt
81
https://docs.raku.org/routine/dir
ADDENDUM: My inspection of the Raku P5-to-P6 Glossary suggests that the designers deliberately left Perl5's glob
function out of Perl6/Raku, opting instead for a more-powerful built-in dir()
routine. Links below:
https://docs.raku.org/language/5to6-perlfunc#index-entry-glob_-_perlfunc https://docs.raku.org/routine/dir
Raku module IO::Glob
is non-core (and..I've never tried it). But if you're working at the command line and want to load a module, you use (for example) -MIO::Glob
followed by -e
, -ne
, or -pe
, etc. (Also, no need to incorporate a use IO::Glob;
line within your Raku one-liner, it's loaded via -M
already).
See Raku one-liner examples with the Txt::CSV
module and/or XML
module at the links below:
https://unix.stackexchange.com/search?q=%5Bcsv%5D+Raku
https://unix.stackexchange.com/search?q=%5Bxml%5D+Raku
Follow additional Windows CMD.exe discussion/resolution below:
https://github.com/rakudo/rakudo/issues/4550
The general answer - Its not a bug. Windows programs have to deal with their own globbing if they want it. Making it work in the raku executable makes sense to me; it removes platform specific surprises, and makes one-liners easier.
But others didn't see it that way, and there is an easy enough solution - create your own module so that the code can remain consistent and be called relatively simply.
Here's a module for starters. There is room to add things like
The module:
unit module CLGlob:ver<1.0>:auth<pureabsolute>;
use IO::Glob;
@*ARGS = map { .Str }, (map { glob(.IO.basename).dir(.IO.dirname) }, @*ARGS ).flat;
Note: the expression in the second map can be simplified when the glob function works for windows with directories.
Note: I convert each element to .Str to make @*ARGS consistent. The $*ARGFILES worked without doing that so some processing can be saved if you'll never look at the @*ARGS again.
Finally, the end result:
raku -MCLGlob -ne ".say" ..\*.file ..\*.file2
Yay.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With