How to get file last modified time with Perl 5.004 and no modules - windows

I have a standalone version of Perl for Windows (5.004) that does not include any modules. I want to run a script to check the last modified time of several files.
I could use File::qstat, but that module doesn't exist (the copy of Perl is in version control, so it can be used by people who do not have ActivePerl or Strawberry Perl installed).
It seems like there are three options:
Figure out how to put a newer, more functional, standalone Perl installation into version control
Just add the File::Stat module somehow, and do use lib (does that work on 5.004?)
Use some built-in functions included in 5.004 for Windows to get the file status.
How can I do this?

perl -le '$file=shift or die;print scalar localtime((stat($file))[9])' file
See stat .

Why on earth are you stuck using Perl 5.004? I have source from Perl 5.5.3 dated in 1999, so Perl 5.004 is likely to be several years older than that. (I found source for Perl 5.004_04 after all; the latest timestamp in that was 1997-10-15 06:46.) So, that's about 15 years old.
The stat function is likely to exist and do the job you need.

Related

Running perl script with Scalar::Util fails with "Attempt to reload Scalar/Util.pm aborted."

I have recently switched to a Mac Book Pro M1 (from Ubuntu) and installed Perl from homebrew.
I've installed a number of perl packages I commonly use without any issues. Unfortunately at runtime any perl programs that depend on (or use a package that depends on) Scalar::Util or List::Util fail with errors like:
Attempt to reload Scalar/Util.pm aborted.
Compilation failed in require at /opt/homebrew/Cellar/perl/5.34.0/lib/perl5/site_perl/5.34.0/YAML.pm line 21.
BEGIN failed--compilation aborted at /opt/homebrew/Cellar/perl/5.34.0/lib/perl5/site_perl/5.34.0/YAML.pm line 21.
...
or
Can't load '/opt/homebrew/Cellar/perl/5.34.0/lib/perl5/site_perl/5.34.0/darwin-thread-multi-2level/auto/List/Util/Util.bundle' for module List::Util: dlopen(/opt/homebrew/Cellar/perl/5.34.0/lib/perl5/site_perl/5.34.0/darwin-thread-multi-2level/auto/List/Util/Util.bundle, 0x0001): symbol not found in flat namespace (_Perl_croak_memory_wrap) at /System/Library/Perl/5.30/XSLoader.pm line 96.
at /opt/homebrew/Cellar/perl/5.34.0/lib/perl5/site_perl/5.34.0/darwin-thread-multi-2level/List/Util.pm line 24.
Compilation failed in require at /opt/homebrew/Cellar/perl/5.34.0/lib/perl5/site_perl/5.34.0/darwin-thread-multi-2level/Scalar/Util.pm line 23.
I've also tried to install perlbrew as an alternative but haven't succeeded there. I've also checked that everything appears in the PERL5LIB path correctly.
With List::Util I've managed to install a newer version from CPAN but still get the same error. (The builtin Scalar::Util is the latest version)
Any suggestions on what to try to get them working I fear that it's an M1 issue but I'm not sure it could be an xcode issue I guess.
You can replicate this with:
$ cpanm VCSL::Which
$ vcsvimdiff -v
Can't load '/opt/homebrew/Cellar/perl/5.34.0/lib/perl5/site_perl/5.34.0/darwin-thread-multi-2level/auto/List/Util/Util.bundle' for module List::Util: dlopen(/opt/homebrew/Cellar/perl/5.34.0/lib/perl5/site_perl/5.34.0/darwin-thread-multi-2level/auto/List/Util/Util.bundle, 0x0001): symbol not found in flat namespace (_Perl_croak_memory_wrap) at /System/Library/Perl/5.30/XSLoader.pm line 96.
at /opt/homebrew/Cellar/perl/5.34.0/lib/perl5/site_perl/5.34.0/darwin-thread-multi-2level/List/Util.pm line 24.
Compilation failed in require at /opt/homebrew/Cellar/perl/5.34.0/bin/vcsvimdiff line 12.
BEGIN failed--compilation aborted at /opt/homebrew/Cellar/perl/5.34.0/bin/vcsvimdiff line 12.
Unfortunately running
perl -MScalar::Util -e 1
or
perl -MList::Util -e 1
both run successfully. I looked at my PERL5LIB path and only see the homebrew perl paths there.
$ perl -E 'say join "\n", split /:/, $ENV{PERL5LIB}'
/opt/homebrew/Cellar/perl/5.34.0/lib/perl5
/opt/homebrew/Cellar/perl/5.34.0/lib/perl5/site_perl/5.34.0
/opt/homebrew/Cellar/perl/5.34.0/lib/perl5
/opt/homebrew/Cellar/perl/5.34.0/lib/perl5/site_perl/5.34.0
/opt/homebrew/Cellar/perl/5.34.0/lib/perl5
/opt/homebrew/Cellar/perl/5.34.0/lib/perl5/site_perl/5.34.0
All that looks fine with no system perl references
The summary:
check that you aren't missing something
check perl -V to see which perl it is and it's default module search path
check environment variables such as PERL5LIB for conflicting values
look in the shebang line for the programs you are running
Do you have everything?
As HÃ¥kon noted, it looks like there are two perl installations interfering with each other. But, also as ikegami said "never seen that" error message. I haven't either, but StackOverflow has seen it.
The entry in [perldiag] is says that the program tried to load the module, failed the first time, and then something tried again:
Attempt to reload %s aborted.
(F) You tried to load a file with "use" or "require" that failed to
compile once already. Perl will not try to compile this file again
unless you delete its entry from %INC. See "require" in perlfunc and
"%INC" in perlvar.
I don't know what keeps it from failing the first time, but you should check with something simple to see if you can load the module:
$ perl -MScalar::Util -e 1
But, it's actually more tricky than this. Maybe that perl can load it, but some other perl can't. And, maybe you have multiple installations of Scalar::Util, but the particular perl and environment and program settings conspire to choose the wrong one.
The environment can tell perl where to look
But, perhaps none of that works.
First, figure out which perl you want to use, and check its settings:
$ perl -V
At the end of the output you should see the interesting environment settings and the default module search path. With a clean session, I don't have any environment variables that contain PERL:
%ENV:
#INC:
/usr/local/perls/perl-5.36.0/lib/site_perl/5.36.0/darwin-2level
/usr/local/perls/perl-5.36.0/lib/site_perl/5.36.0
/usr/local/perls/perl-5.36.0/lib/5.36.0/darwin-2level
/usr/local/perls/perl-5.36.0/lib/5.36.0
However, I can dirty up my environment. I'll set a PERL5LIB value, which prepends directories to the default module search path:
$ export PERL5LIB=/usr/local/perls/perl-5.10.1/lib/5.10.1/darwin-2level:/usr/local/perls/perl-5.10.1/lib/5.10.1:/usr/local/perls/perl-5.10.1/lib/site_perl/5.10.1/darwin-2level:/usr/local/perls/perl-5.10.1/lib/site_perl/5.10.1
Check perl -V again and this interesting thing happens:
Perl lib version (5.10.1) doesn't match executable version (v5.36.0) at /usr/local/perls/perl-5.10.1/lib/5.10.1/darwin-2level/Config.pm line 50.
Compilation failed in require.
BEGIN failed--compilation aborted.
If I try to load Scalar::Util from the command line with -M, which is what I'd expect if you've mixed up the perls:
$ perl -MScalar::Util -e 1
Can't load '/usr/local/perls/perl-5.10.1/lib/5.10.1/darwin-2level/auto/List/Util/Util.bundle' for module List::Util: dlopen(/usr/local/perls/perl-5.10.1/lib/5.10.1/darwin-2level/auto/List/Util/Util.bundle, 0x0001): symbol not found in flat namespace '_PL_sv_no' at /usr/local/perls/perl-5.10.1/lib/5.10.1/darwin-2level/XSLoader.pm line 73.
at /usr/local/perls/perl-5.10.1/lib/5.10.1/darwin-2level/List/Util.pm line 23
Compilation failed in require at /usr/local/perls/perl-5.10.1/lib/5.10.1/darwin-2level/Scalar/Util.pm line 23.
Compilation failed in require.
BEGIN failed--compilation aborted.
Programs may be incorrectly adjusting #INC
I don't think this is a problem with cpanm because the world would have complained by now. However, if some program is doing funky things with #INC, it may be adding the wrong things.
I think the likely case for this is a set of vendor module directories they use and that some of those modules are targeted at a particular perl. When you use a different perl, you get the binary mismatch thing.
Programs choose their interpreter
MacOS: two Perl installs: "Dumper.c: loadable library and perl binaries are mismatched" notes that their home-brew cpanm was hardcoded to use the system perl.
But, there's another part involved. You are running some programs, and those programs choose the perl. If you look at their first lines, they either have an absolute path to a perl, like this:
#!/usr/bin/perl
Or they play a trick to find the first perl in your PATH:
#!/usr/bin/env perl
I don't like that second one because I'm never sure which perl it will find first. In Mastering Perl, I have a long example of someone calling a program "perl", dropping it in a user-controlled directory in PATH (or adding that to PATH for you), then acting like its the real perl but turning off taint-checking along the way. Probably not your problem, but when you let the program guess who is going to handle it weird things can happen.
For example, I guess I haven't installed cpanm for v5.36.0 yet:
$ head -1 `which cpanm`
#!/usr/local/perls/perl-5.34.1/bin/perl
When I run just cpanm, it's going to use v5.34.1 and whatever settings I have for that.
I could tell it directly which perl to use, but I then need to tell that perl where to find the program:
$ perl5.36.0 `which cpanm` ...
Likewise, I have older versions of some programs that I address with the version I intend to use (I do a lot of stuff that runs something against many, many perls):
$ head -1 `which cpan5.10.1`
#!/usr/local/perls/perl-5.10.1/bin/perl
$ head -1 `which cpan5.12.5`
#!/usr/local/perls/perl-5.12.5/bin/perl
When you install programs, such as cpanm, the installation adjusts the shebang line for the perl that installed it. Simply running cpanm does not mean that you are installing into the perl you think you are.

cpan vs -MCPAN - Perl

I'm currently running bash via Cygwin on Windows, and I've come across two different ways to install a Perl module
cpan Name::Module
and
perl -MCPAN -e shell
install Name::Module
What's the difference between these two methods, and do they offer any advantages or disadvantages over the other?
cpan installs for the perl in the shebang (#!) line of the cpan file.
When someone has more than one perl installed on a machine, they sometimes run the wrong copy of cpan, and thus end up installing modules for the wrong instance of perl.
One solution to that would be to specify the full path to the correct cpan file.
perl -MCPAN -e shell is the other solution. It allows you to explicitly specify the install of perl for which you want the modules to be installed.
cpan on Windows just calls App::Cpan->run( #ARGV ), which should give you the same shell as the other command, maybe with other settings active. But I think it's the same. So you could use both. I prefer just cpan and then do install Name::Module, since I tend to look if it's installed before and which version in the cpan shell beforehand.

ARFF file extension to csv binary executable

Thanks in advance for the help.
I'm looking for a binary executable to convert an .arff into a .csv in a bash script. Ideally something that I could run along the lines of
#! /bin/sh
... some stuff....
converstionFunc input.arff output.csv
... some more stuff ...
Looking into writing this myself I found that weka provides a library that I could utilize that would allow me to do this. However, as much as I looked for it, I could not find it. I have weka installed on my mac and after looking around for the library I still was unable to find it.
Does anyone know where I may find such an executable, or able to point me where I could get a hold of the weka java library that would let me write it myself?
Clone this github repository. It contains an arff2csv tool in the "tools" subdirectory.
arff2csv is designed to run in pipes of unix commandline tools.
https://github.com/jeroenjanssens/data-science-at-the-command-line
arff2csv is a one-line shell-script that calls another shell script that calls weka.jar,
so it needs java installed on your machine; and note that arff2csv needs Weka version 3.6. (According to my experiments the newer v3.7 does not work.)
The script wants this environment variable set:
export WEKAPATH=/path/to/wekajar-dirname
and then you can do
cat /opt/smallapps/weka-stable/data/breast-cancer.arff | arff2csv > breast-cancer.arff.csv
Large arffs need some time to get processed.
You can read J.Janssen's book (see repo-README) for a bit more info.
Try an web search for arff2csv. It looks like there are lots of utilities out there.

How can I make a Perl script executable in Windows 64bit?

I am trying to run the perl script through command line but it is not reorganizing the script file ie.
myscript.pl... is not working
but perl myscript.pl is working fine
I have tried the following suggestions but they didn't work either
How do I make my Perl scripts act like normal programs on Windows?
Perl execution from command line question
I am using Active Perl:- Perl 5 , Version 18.
It gives following warnings in both cases.
Using a hash as a reference is deprecated
earlier I installed strawberry perl before installing active perl, is that causing some problem.
The error message
Using a hash as a reference is deprecated
is a Perl message. Your script is being run just fine, but contains an error.
(It is remotely possible that you have two Perl versions installed, and that you configured Windows to use the wrong one. Reconfigure it to use the correct on then, using the guides you already found.)

How to use default path for ActivePerl 5.20 Mac OS X (/usr/bin/perl) instead of /usr/local/ActivePerl...?

I have installed ActivePerl 5.20.2 today on Mac OS X 10.9.5
Checking the version of perl in Terminal (perl -v) I see 5.20.2
So everything seems to be ok. But..
When I start my CGI scripts the script is running under built in perl (which is 5.16) (if using #!/usr/bin/perl).
If I use #!/usr/local/ActivePerl5.20.2/bin/perl then it runs under 5.20.2 that is required.
The question is: is it somehow possible to change the directory for using in my scripts from #!/usr/local/ActivePerl5.20.2/bin/perl to simple and familiar #!/usr/bin/perl keeping running under ActivePerl instead of built in.
I need to override the system's default version with the new ActivePerl.
I would be appreciated for your detailed answers (with name of files and directories where they are located) if ones are to be changed to implement salvation.
Thanks!
The question is: is it somehow possible to change the directory for using in my scripts from #!/usr/local/ActivePerl5.20.2/bin/perl to simple and familiar #!/usr/bin/perl keeping running under ActivePerl instead of built in.
Don't even try. That way lies damnation, not salvation. The ability to specify the specific interpreter that will handle your scripts is an important feature.
Instead, package your CGI script as a simple CPAN module. Then, install it using the familiar
$ /usr/local/ActivePerl5.20.2/bin/perl Makefile.PL
$ make install
routine. The shebang line will be automatically adjusted to reflect the perl that was used to build and install your package.
First, instead of specifying a particular path to your Perl interpreter in your script:
#! /usr/local/ActivePerl5.20.2/bin/perl
or
#! /usr/bin/perl
Specify this:
#! /usr/bin/env perl
This will find the first executable Perl interpreter in your $PATH and then use that to execute your Perl script. This way, instead of having to change your program, you only have to change the $PATH variable.
Next time, take a look at PerlBrew for installing a different version of Perl. PerlBrew will allow you to install multiple versions of Perl all under user control, and let you select which version of Perl you'd like to use.
I also recommend to put /usr/local/bin as the first entry in your $PATH. Then, link the executables you want to run to that directory. You can use something like this to create your links:
for file in $/usr/local/ActivePerl5.20.2/bin/*
do
basename=$(basename $file)
ln -s "$file" "/usr/local/bin/$basename"
done
This way, all programs you want to execute are in the same directory which makes setting $PATH so much easier. I even put /usr/local/bin in before /usr/bin and /bin because I want to be able to override the system's default version.

Resources