How do I execute a command using a local program in OCaml? - command-line

So the default way to execute commands in OCaml is Sys.command s where s is the command in this case, but I come across an issue when the command involves a local program. For example, if I have an executable named prog I compiled from an ocaml file, and I use Sys.command "prog {args}", I get back an error saying 'prog' is not recognized as an internal or external command, operable program or batch file. And using the command ./prog {args} doesn't seem to change anything either, since then it says '.' is not recognized as an internal or external command, operable program or batch file. Any advice?

Probably the problem is in the prog and lies outside of the OCaml, in other words, your prog is not a program, so the operating system can't run it.
Here is an example, that works perfectly for me:
$ cat > test << EOF
#!/bin/sh
echo hello
EOF
$ chmod a+x test
$ ocaml
# Sys.command "./test";;
hello
- : int = 0

So, one of the above users was right: in Windows, the batch files produced by ocamlc cannot be executed. Instead, an easy workaround is just to compile by appending the .exe tag to the file name you want to produce e.g. ocamlc -o prog.exe myfile.ml. Then, just use Sys.command "prog.exe {args}" instead.

Related

Unable to execute Perl script unless Perl is inserted before script name

Running Lubuntu -
Beginner Perl programmer
Script is XXX.pl located at ~/projects/XXX/XXX.pl
First line is the shebang
#!/usr/bin/perl
Permission to run is set to Anyone.
In directory ~/projects/XXX, the command
~/projects/XXX$ perl XXX.pl
works as desired, but the command
~/projects/XXX$ XXX.pl
Fails with XXX.pl: command not found
What am I missing ?
The two usual options to execute your Perl script are:
perl XXX.pl
or
./XXX.pl
Both ways assume that your current working directory contains the script XXX.pl, otherwise it won't work.
As already pointed out by jm666 in the comments, you can usually not execute a program or script from your current working directory without prepending ./, primarily because of security reasons. Now, you may wonder why it's necessary.
Explanation:
Your shell uses the contents of an environment variable called $PATH to find out about where external commands (non-builtin programs) are located in your filesystem. If you want to see what's in $PATH, just type the following in your shell:
echo $PATH
Now you can see that the $PATH variable does NOT contain your current working directory. The consequence is that your shell is not able to find the program XXX.pl. By prepending ./ you instruct the shell to execute the program which comes after.
But there are two requirements if you want to execute your Perl script with ./script.pl:
The script has to be executable (check with ls -l)
The first line (shebang line) has to be #!/path/to/your/perl because your shell needs that information to find the perl interpreter in order to run your script
However, #1 and #2 are NOT required when you execute your script with
perl XXX.pl
because it invokes the perl interpreter directly with your script.
See how to make Perl scripts executable on Linux and make the script itself directly executable with chmod for some more details.
Can the script be found?
Is . in your path? If it's not, add it to your path, or use ./XXX.pl instead of XXX.pl.
Can the script be executed?
Do you have execute permission to the file? Fix using chmod u+x XXX.pl.
Is the interpreter correct?
which perl will tell you which interpreter is used when you use perl XXX.pl. That's the path that should be on your shebang (#!) line.

redirecting echo with undefined variable

I'm running a script in solaris 11 with different results depending of the shell used.
The script has an echo redirecting to a file given by an environment value:
echo "STARTING EXEC" >> $FILE
ps. EXEC is just the message the script show, it's not using exec command.
If I execute the script without the variable FILE defined (using /usr/bin/ksh):
./start.sh[10]: : cannot open
and the script continue the execution.
The flags for ksh are:
echo $-
imsuBGEl
But if I change to /usr/xpg4/bin/sh, the script show me the echo in stdout and there is no error shown.
The flags for xpg4 sh are:
echo $-
imsu
I tried to change the flags with set +- (I can't remove El flags, but BG are removed ok), but can't get the same behavior.
Is there anything I can do to get the same result using ksh without cannot open error?
/usr/bin/ksh --version
version sh (AT&T Research) 93u 2011-02-08
I'll want the script keep going, showing the message in stdout, instead of showing the error just like it does now.
Like shellter said in the comments, the good thing to do is to check if the FILE variable is defined before doing anything. This is a script migration from an HPUX to a SOLARIS environment, and client think they must have the same result as before (we unset FILE variable before execution to test it).
You are likely running Solaris 11, not Solaris 64.
Should you want to have your scripts to work under Solaris 11 without having to search everywhere the bogus redirections, you can simply replace all shebangs (first line) by #!/usr/xpg4/bin/sh.
The final solution we are going to take is to install the ksh88 package and use it like default shell (/usr/sunos/bin/ksh). This shell have the same behavior the client had before, and we can let the scripts with no modifications.
The ksh used in solaris 11 is the 93 (http://docs.oracle.com/cd/E23824_01/html/E24456/userenv-1.html#shell-1)
Thanks #jlliagre and #shellter for your help.

run specific perl script from command line

Not that much experience programming, but I saw this open source code for one of those speed readers everyone is talking about and thought it would be cool to try to run it on my own computer.
The files are available here: https://github.com/pasky/speedread
I was wondering what exactly I should type into the command prompt to get the program running. I already have a perl interpreter on my computer. But I'm not sure how to get the program running. Sorry if this is a super noobish question.
I've tried
perl C:\speadread-master\speedread (and yes, it was on the C: drive)
I got the error:
Use of encoding pragma is deprecated at C:\speadread-master\speedread line 39.
'stts' is not recognized as an internal or external command, operable program of batch file.
←[31mc←[0←[K
I also tried (because it appears in the gifs on github)
~/speedread$ head -n 21 tea.txt | ./speedread -w 250
I got the error:
'~' is not recognized as an internal or external command, operable program or batch file
In addition to amon's comment, wo points out a strong dependency to Unix commands/display, you also misinterpreted the head command:
~/speedread$ is a Unix command prompt, with ~ refering to your HOME directory (USERPROFILE in Windows). You are not supposed to type it.
The actual command is:
head -n 21 tea.txt | ./speedread -w 250
Adn you have an head.exe (Windows version of the unix command head) in your git msysgit distribution (bin/head.exe).

Running Executable from Shell Script

I am having trouble launching an executable that I have created from a shell script. I would like to automate testing by running the program many times with different command line options to verify it is working.
When I type echo $SHELL, /bin/sh is displayed.
The following is my shell script:
#!/bin/sh
clear
echo "Running first test."
./myProgram
exit 0
When I run the script (sh myScript.sh), with myProgram in the same directory, I see the following output:
Running first test.
: not foundsh: line 4:
When executing the program ./myProgram, it runs as expected with no command line options.
I have also tried:
myProgram
./myProgram &
myProgram &
based on answers to somewhat similar questions, but they all result in the above error message.
Your newlines are goofed. Use dos2unix to fix.
why don't you try using the full path?
e.g., if myProgram is in /home/user1/bin, you can try /home/user1/bin/myProgram instead of ./myProgram. This should work.
You can also add the path to path variable, $PATH and directly call myProgram from anywhere.
Run "export PATH=$PATH:/home/user1/bin" on your terminal without the quotes. Note that this affects only your current termial session. If you want to permanently add the path, update your .bashrc file in your home directory with the following line:

How is this zip command being used in perl?

I found this piece of code in perl
system("zip $ZIP_DEBUG -r -9 itvlib.zip $include $exclude");
However I don't understand how it is working. I mean system() is used to fire 'system' commands right ? So is this 'zip' command used here a 'system' command ?
But I tried firing just the following on the command prompt;
zip $ZIP_DEBUG -r -9 itvlib.zip arg1 arg2
It didn't work !
it gave the following error:
'zip' is not recognized as an internal or external command,
operable program or batch file.
Well this shouldn't have happened, since the command seems to use 'zip' as a system command. So this makes the command 'zip' mysterious
Can you please help me to understand this command with all its parameters?
It's probably not working since you're not replacing things like $ZIP_DEBUG with their equivalent real values. Within Perl, they will be replaced with the values of the variables before being passed to the system call.
If you print out those Perl variables (or even the entire command) before you execute that system call, you'll find out those real values that you need to use. You can use the following transcript to guide you:
$ perl -e '
> $ZIP_DEBUG = "xyzzy";
> $include = "inc_files";
> $exclude = "exc_files";
> print "zip $ZIP_DEBUG -r -9 itvlib.zip $include $exclude";
> '
zip xyzzy -r -9 itvlib.zip inc_files exc_files
For details on how system works, see here. For details on what zip needs to function, you should just be able to run:
man zip
from a command line shell (assuming you're on Linux or its brethren). If, instead, you're on a different operating system (like Windows), you'll have to figure out how to get the zip options out. This may well be as simple as zip -? of zip -h but there's no guarantee that will work.
If it's the same as the Info-ZIP zip under Linux (and it may be if you have the -9 and -r options and your exclude variable starts with -x), then zip -h will get you basic help and zip -h2 will give you a lot more.
system("zip $ZIP_DEBUG -r -9 itvlib.zip $include $exclude");
is running a program named zip (probably zip.exe) somewhere on the path. $ZIP_DEBUG, $include, and $exclude are Perl variables that are interpolated into the command line before the command is run.
If the system call works in the Perl script, but zip -? gives the 'zip' is not recognized as an internal or external command, operable program or batch file error, then the PATH of the Perl script must be different than the PATH in your command prompt. Or, there might be a zip command in the current directory when Perl executes the system command. (In Windows, the current directory is an implicit member of your PATH.)
To see what the PATH is for the Perl script, you can add a print "$ENV{PATH}\n"; before the system command. To see what the PATH is in your command prompt, type PATH.
Yes, zip is a system command. The variables $ZIP_DEBUG and such are perl variables that are interpolated to the command before launching zip.
To debug what the actual call is, try adding:
print("zip $ZIP_DEBUG -r -9 itvlib.zip $include $exclude\n");
See perldoc for details on system.