FInding relative path in Perl - perl

I have the following code in a perl module,
package Foo;
our $pathToScript = "/home/Lucas/project841/python_script.py";
It is frequently called by other modules in the same file directory through
$output = `$Foo::pathToScript`;
# etc
I would like to remove the hard coding of the actual path and use relative path, Eg. ./python_script.py to call the script from other modules.
What would be the ideal way?

You said your Perl script is "frequently" called from the same directory where the Python script resides, not "always". If you remove the absolute path, you'll need to change that "frequently" to "always", and just change $pathToScript to the Python script name (no path).
You could also consider setting the environment PATH (in the Perl script) so that the Python script (without the full path in $pathToScript) is always found, regardless of where the user is running from or where the Perl script is located.

Related

Cwd::abs_path broken on msys, cygwin

I'm trying to get the absolute path to a file provided as a Windows path in Cygwin, respectively Msys (Git Bash) perl. I would like solutions that also work when the supplied path is a "native" Cygwin/MSys path.
I tried using Cwd::abs_path, but that seems subtly broken. Here is a test:
user#MYPC MINGW64 /f/Temp
$ perl
use Cwd;
print Cwd::abs_path("F:\\") . "\n";
print Cwd::abs_path("F:\\test.txt") . "\n";
print Cwd::abs_path("..\\test.txt") . "\n";
/f
/f/Temp/F:/test.txt
/f/Temp/../test.txt
Directories work, relative paths "work" but don't give the result I'd expect (i.e. .. is not eliminated), but when I add a filename to an absolute path the result is wrong. I had hoped that Cwd would do the path translation for me.
I need to later extract parts of the path (using the functions from File::Spec) and also want open the file. To continue working with the extracted part the path should be native to the perl version used. I want to avoid using cygpath, since I'd like the script to also work with ActivePerl, which understands Windows paths only. I could of course add some ifs to only call cygpath for the unix-y perls.
You do not have an absolute path. msys and cygwin are unix emulation environments, and in unix, absolute paths start with /. F:\ is a valid relative path and file name in unix.
Linux$ touch 'F:\'
Linux$ ls
F:\
In cygwin, /cygdrive/f/ refers to your F:. You can use the command-line utility cygpath to convert between native and Windows paths.
cygwin$ cygpath -w /cygdrive/c/
C:\
cygwin$ cygpath -u 'C:\'
/cygdrive/c/
msys should also have a way of accessing the Windows drive through its virtual unix file system.

Execute perl script using mason template

I have installed Mason module from cpan. Now i am executing my first program using mason template.
first_mason.mc
% my $name = "Mason";
Hello world! Welcome to <% $name %>.
first_mason.pl
#!/usr/local/bin/perl
use Mason;
my $mason = Mason->new(comp_root => '...');
print $mason->run('first_mason.mc')->output;
This throws an error as follows
first_mason.mc is not an absolute path at C:/Perl/site/lib/Mason/Request.pm line 256**
Note
I am placing both files in the path where mason is installed(to find an installation path ,i used perldoc -l Mason) and executed a program using perl first_mason.pl
There is no need to put your files in the directory where Mason is installed:
Perl should know where to find Mason when you import it with use (assuming your perl installation is correct).
Mason will know where to find the .mc file via the comp_root argument.
The component name needs to be specified as a path relative to comp_root, always beginning with /.
You need to leave out the .mc from the component name.
So, if you place the 2 files in your home directory, then the script should look like this:
#!/usr/local/bin/perl
use Mason;
my $mason = Mason->new(comp_root => $HOME_DIR); # where $HOME_DIR is `C:\User\your_name`
print $mason->run('/first_mason')->output;
From the documentation:
The component root and component paths
When you use Mason, you specify a component root that all component
files live under. Thereafter, any component will be referred to by its
virtual path relative to the root, rather than its full filename.
For example, if the component root is '/opt/web/comps', then the
component path '/foo/bar.mc' refers to the file
'/opt/web/comps/foo/bar.mc'.
#stevenl fully answers your question. Simply don't blindly copy the Synopsis from the Mason docs, need read the docs too. :) E.g. in the example code:
#!/usr/local/bin/perl
use Mason;
my $mason = Mason->new(comp_root => '...');
print $mason->run('/foo')->output;
you need replace
and the shebang line #!/usr/local/bin/perl with the real path to your perl interpreter
the '...' with the real path in the filesystem, where your component are, e.g.
comp_root => '/some/real/path/here/where/my/component/root/is'
However, I wrote this answer mainly with a reason: if you want use the Mason for the web-app development, check the Poet module too. It GREATLY simplifies the whole process, and you will not need care about many-many things. E.g. after installing the Poet you can simply:
poet new MyApp
myapp/bin/run.pl
and you will immediately get (without any configuration) an WORKING web-app, and you could access it in your browser at http://localhost:5000. Your component_root will be inside of the myapp directory as myapp/comps.

Creating files at PSModulePath in batch

I am currently trying to write a batch program that installs a module named SetConsolePath.psm1 at the correct location. I am a beginner with Batch and I have absolutely no powershell experience.
Through the internet, I have learned how to display PSModulePath with powershell -command "echo $env:PSModulePath.
How can I, via .bat file, move SetConsolePath.psm1 from the desktop to the location displayed by powershell -command "echo $env:PSModulePath?
Thank you in advance, and I apologize for my lack of experience.
Before I answer, I must out that you do not want to copy PowerShell module files directly to the path pointed by PsModulePath. You really want to create a folder inside PSModulePath and copy the files there instead.
The prefix env in a Powershell variable indicates an environment variable. $env:PSModulePath is actually referring to the PSMODULEPATH environment variable. On the command line, and in batch files, environment variables can be displayed by placing the name between percent symbols. (In fact, you could have displayed this value by typing echo %PSMODULEPATH% instead.)
To reference the desktop folder, have a look at this answer, which shows you how to use another environment variable, USERPROFILE.
Therefore, to copy the file from the desktop directory to the path specified in PSModulePath, you would do this:
COPY "%USERPROFILE%\Desktop\SetConsolePath.psm1" "%PSMODULEPATH%"
And, as I warned earlier, you really should copy the file to a folder underneath PsModulePath. So what you really want is:
IF NOT EXIST "%PSMODULEPATH%\MyNewFolder" MKDIR "%PSMODULEPATH%\MyNewFolder"
COPY "%USERPROFILE%\Desktop\SetConsolePath.psm1" "%PSMODULEPATH%\MyNewFolder"

Running a script in bash

I have a script in one of my application folders.Usually I just cd into that locatin in Unix box and run the script e.g.
UNIX> cd My\Folder\
My\Folder> MyScript
This prints the required result.
I am not sure how do I do this in Bash script.I have done the following
#!/bin/bash
mydir=My\Folder\
cd $mydir
echo $(pwd)
This basically puts me in the right folder to run the required script . But I am not sure how to run the script in the code?
If you can call MyScript (as opposed to ./MyScript), obviously the current directory (".") is part of your PATH. (Which, by the way, isn't a good idea.)
That means you can call MyScript in your script just like that:
#!/bin/bash
mydir=My/Folder/
cd $mydir
echo $(pwd)
MyScript
As I said, ./MyScript would be better (not as ambiguous). See Michael Wild's comment about directory separators.
Generally speaking, Bash considers everything that does not resolve to a builtin keyword (like if, while, do etc.) as a call to an executable or script (*) located somewhere in your PATH. It will check each directory in the PATH, in turn, for a so-named executable / script, and execute the first one it finds (which might or might not be the MyScript you are intending to run). That's why specifying that you mean the very MyScript in this directory (./) is the better choice.
(*): Unless, of course, there is a function of that name defined.
#!/bin/bash
mydir=My/Folder/
cd $mydir
echo $(pwd)
MyScript
I would rather put the name in quotes. This makes it easier to read and save against mistakes.
#!/bin/bash
mydir="My Folder"
cd "$mydir"
echo $(pwd)
./MyScript
Your nickname says it all ;-)
When a command is entered at the prompt that doesn't contain a /, Bash first checks whether it is a alias or a function. Then it checks whether it is a built-in command, and only then it starts searching on the PATH. This is a shell variable that contains a list of directories to search for commands. It appears that in your case . (i.e. the current directory) is in the PATH, which is generally considered to be a pretty bad idea.
If the command contains a /, no look-up in the PATH is performed. Instead an exact match is required. If starting with a / it is an absolute path, and the file must exist. Otherwise it is a relative path, and the file must exist relative to the current working directory.
So, you have two acceptable options:
Put your script in some directory that is on your PATH. Alternatively, add the directory containing the script to the PATH variable.
Use an absolute or relative path to invoke your script.

Can't exec No such file or directory

Merry Christmas to everybody. I'm having a dilemma with a perl script. In my script, I call another program with a system call, but I got this error:
Can't exec "./Classificador/svm_classify": No such file or directory at Analise_de_Sentimentos_mudanca.pl line 463.
I don't know if there is a problem in having my program in a different directory than the called program.
Another curious thing is that this script used to run normally in Ubuntu 10.10. But now I've changed to Mint 14. Is it missing some library?
Best wishes,
Thiago
The relative pathname ./Classificador/svm_classify is interpreted relative to the user's current directory, not the directory containing the perl script. You need to do one of the following:
The user must cd to the directory containing the perl script before running it.
The perl script should call chdir() to set the current directory to the directory where it's stored.
Put the absolute pathname in the script, instead of ./.
Does this "./Classificador/svm_classify" exists ?
Check the following :
1) to go the directory where this file lays - Analise_de_Sentimentos_mudanca.pl
2) run :
ll Classificador/svm_classify
3) show us the results