Is it possible to override hashbang/shebang path behavior - windows

I have a bunch of scripts (which can't be modified) written on Windows. Windows allows relative paths in its #! commands. We are trying to run these scripts on Unix but Bash only seems to respect absolute paths in its #! directives. I've looked around but haven't been able to locate an option in Bash or a program designed to replace and interpreter name. Is it possible to override that functionality -- perhaps even by using a different shell?

Typically you can just specify the binary to execute the script, which will cause the #! to be ignored. So, if you have a Python script that looks like:
#!..\bin\python2.6
# code would be here.
On Unix/Linux you can just say:
prompt$ python2.6 <scriptfile>
And it'll execute using the command line binary. I view the hashbang line as one which asks the operating system to use the binary specified on the line, but you can override it by not executing the script as a normal executable.
Worst case you could write some wrapper scripts that would explicitly tell the interpreter to execute the code in the script file for all the platforms that you'd be using.

Related

Instead of giving command for batch mode, give .scm file path?

It is possible to supply batch commands directly with the -b flag, but if the commands become very long, this is no longer an option. Is there a way to give the path to an .scm script that was written to a file, without having to move the file into the scripts directory?
No as far as I know. What you give in the -b flag is a Scheme statement, which implies your function has already been loaded by the script executor process. You can of course add more directories that are searched for scripts using Edit>Preferences>Folders>Scripts.
If you write your script in Python the problem is a bit different since you can alter the Python path before loading the script code but the command line remains a bit long.

Shell script sh executable - edit to see script

Is there a way to see the original code of a executable sh script. (I am very new to Linux and trying to understand what things do and such.)
If you know how I need very clear step by step process so I can just type i the commands and run them.
Thanks for your help. Trying to learn (Windows man for 25 years here)
A shell script specifically can be seen in the original text form by simply printing the contents of the file:
cat disk-space.sh.x
Several caveats:
If you mean an executable rather than a script the situation is different. Scripts are read by an interpreter at runtime, which then executes it line by line. Executables may be either scripts or ELF binaries. The latter have been transformed from the original source code to a machine readable form which is very much harder to read for humans.
The extension of the file (.sh.x or .x) does not control whether the file contents are executed as a binary or script.
If the file really is a script it may have been obfuscated, meaning that the source code on your system has deliberately been changed to make the resulting file hard to read.

Is it possible to have separate bash completion functions for separate commands which happen to share the same name?

I have two separate scripts with the same filename, in different paths, for different projects:
/home/me/projects/alpha/bin/hithere and /home/me/projects/beta/bin/hithere.
Correspondingly, I have two separate bash completion scripts, because the proper completions differ for each of the scripts. In the completion scripts, the "complete" command is run for each completion specifying the full name of the script in question, i.e.
complete -F _alpha_hithere_completion /home/me/projects/alpha/bin/hithere
However, only the most-recently-run script seems to have an effect, regardless of which actual version of hithere is invoked: it seems that bash completion only cares about the filename of the command and disregards path information.
Is there any way to change this behavior so that I can have these two independent scripts with the same name, each with different completion functions?
Please note that I'm not interested in a solution which requires alpha to know about beta, or which would require a third component to know about either of them--that would defeat the purpose in my case.
The Bash manual describes the lookup process for completions:
If the command word is a full pathname, a compspec for the full pathname is searched for first. If no compspec is found for the full pathname, an attempt is made to find a compspec for the portion following the final slash. If those searches do not result in a compspec, any compspec defined with the -D option to complete is used as the default.
So the full path is used by complete, but only if you invoke the command via its full path. As for getting completions to work using just the short name, I think your only option (judging from the spec) is going to be some sort of dynamic hook that determines which completion function to invoke based on the $PWD - I don't see any evidence that Bash supports overloading a completion name like you're envisioning.
Yes, this is possible. But it's a bit tricky. I am using this for a future scripting concept I am developing: All scripts have the same name as they are build scripts, but still bash completion can do its job.
For this I use a two step process: First of all I place a main script in ~/.config/bash_completion.d. This script is designed to cover all scripts of the particular shared script name. I configured ~/.bashrc in order to load that bash completion file for these scripts.
The script will obtain the full file path of the particular script file I want to have bash completion for. From this path I generate an identifier. For this identifier there exists a file that provides actual bash completion data. So if bash completion is performed the bash completion function from the main bash completion script will check for that file and load it's content. Then it will continue with regular bash completion operation.
If you have two scripts with the same name you will have two different identifiers as those scripts share the same name but have different paths. Therefore two different configurations for bash completion can be used.
This concept works like a charm.
NOTE: I will update this answer soon providing some source code.

Coding a relative path to file in OS X [duplicate]

I have a Haskell script that runs via a shebang line making use of the runhaskell utility. E.g...
#! /usr/bin/env runhaskell
module Main where
main = do { ... }
Now, I'd like to be able to determine the directory in which that script resides from within the script, itself. So, if the script lives in /home/me/my-haskell-app/script.hs, I should be able to run it from anywhere, using a relative or absolute path, and it should know it's located in the /home/me/my-haskell-app/ directory.
I thought the functionality available in the System.Environment module might be able to help, but it fell a little short. getProgName did not seem to provide useful file-path information. I found that the environment variable _ (that's an underscore) would sometimes contain the path to the script, as it was invoked; however, as soon as the script is invoked via some other program or parent script, that environment variable seems to lose its value (and I am needing to invoke my Haskell script from another, parent application).
Also useful-to-know would be whether I can determine the directory in which a pre-compiled Haskell executable lives, using the same technique or otherwise.
As I understand it, this is historically tricky in *nix. There are libraries for some languages to provide this behavior, including FindBin for Haskell:
http://hackage.haskell.org/package/FindBin
I'm not sure what this will report with a script though. Probably the location of the binary that runhaskell compiled just prior to executing it.
Also, for compiled Haskell projects, the Cabal build system provides data-dir and data-files and the corresponding generated Paths_<yourproject>.hs for locating installed files for your project at runtime.
http://www.haskell.org/cabal/release/cabal-latest/doc/users-guide/authors.html#paths-module
There is a FindBin package which seems to suit your needs and it also works for compiled programs.
For compiled executables, In GHC 7.6 or later you can use System.Environment.getExecutablePath.
getExecutablePath :: IO FilePathSource
Returns the absolute pathname of the current executable.
Note that for scripts and interactive sessions, this is the path to the
interpreter (e.g. ghci.)
There is executable-path which worked with my runghc script. FindBin didn't work for me as it returned my current directory instead of the script dir.
I could not find a way to determine script path from Haskell (which is a real pity IMHO). However, as a workaround, you can wrap your Haskell script inside a shell script:
#!/bin/sh
SCRIPT_DIR=`dirname $0`
runhaskell <<EOF
main = putStrLn "My script is in \"$SCRIPT_DIR\""
EOF

What does #!perl do exactly?

I recently received a perl script with the first line
#!perl
This of course doesn't work but I would like to know exactly what it does. Can anyone help?
That is called a shebang and is used (in Unix) to specify which interpreter binary should be used to run a script.
It's a very nice mechanism, especially together with the way the file system permissions can be used to turn a script file into something the shell (and program loader) consider to be executable.
It seems the interpreter name must be absolute. The linked text says that a relative name (like the bare perl here) will be interpreted as ./perl, so it might work if executed from the directory the perl binary is in. Not a very common use-case but at least it could work if used that way, i.e. if you want to wrap a perl binary with a script, you want that script to run the binary that's in the same place as the script, and not use absolute paths to pick some other binary. Haven't tested this.
A more typical approach (at least in Linux) is to use the env program to pick the perl:
#!/usr/bin/env perl
If you give the shebang line like this,
#!perl
it will look for the perl interpreter in the current directory. If the perl interpreter exists in the current directory, then the perl script will start to execute otherwise it shows bad interpreter error.

Resources