11

I want to test the output of a bash script when one of the executables it depends on is missing, so I want to run that script with the dependency "hidden" but no others. PATH= ./script isn't an option because the script needs to run other executables before it reaches the statement I want to test. Is there a way of "hiding" an executable from a script without altering the filesystem?

For a concrete example, I want to run this script but hide the git executable (which is its main dependency) from it so that I can test its output under these conditions.

1
  • 1
    Create a virtual machine that has no git in it. Commented Jun 28, 2015 at 11:40

4 Answers 4

10

You can use the builtin command, hash:

hash [-r] [-p filename] [-dt] [name]

Each time hash is invoked, it remembers the full pathnames of the commands specified as name arguments, so they need not be searched for on subsequent invocations. ... The -p option inhibits the path search, and filename is used as the location of name. ... The -d option causes the shell to forget the remembered location of each name.

By passing a non-existent file to the -p option, it will be as if the command can't be found (although it can still be accessed by the full path). Passing -d undoes the effect.

$ hash -p /dev/null/git git
$ git --version
bash: /dev/null/git: command not found
$ /usr/bin/git --version
git version 1.9.5
$ hash -d git
$ git --version
git version 1.9.5
Sign up to request clarification or add additional context in comments.

2 Comments

It doesn't work for me on bash v5 - the correct binary keeps getting hashed. I think the actual usage for hash -p is here which is to create an alias for a binary not in system path. glenn's answer is the correct approach.
@akhan Works here on bash 4.4.12, but maybe v5 updates the hash table if the file isn't found. glenn's anser will certainly be more reliable.
4

Add a function named git

git() { false; }

That will "hide" the git command

To copy @npostavs's idea, you can still get to the "real" git with the command builtin:

command git --version

Comments

1

Since we know the program is running in bash, one solution is to - instead of "hiding" the program - emulate the behaviour of bash in this circumstance. We can find out what bash does when a command isn't found quite easily:

$ bash
$ not-a-command > stdout 2> stderr
$ echo $?
127
$ cat stdout
$ cat stderr
bash: not-a-command: command not found

We can then write this behaviour to a script with the executable name, such as git in the question's example:

$ echo 'echo >&2 "bash: git: command not found" && exit 127' > git
$ chmod +x git
$ PATH="$PWD:$PATH" git
$ echo $?
127
$ cat stdout
$ cat stderr
bash: git: command not found

Comments

0

I created unpath for that:

Usage: unpath UNCMD CMD

unpath runs CMD with a modified PATH that does not contain UNCMD.

Arguments:
  UNCMD the command to hide from PATH
  CMD   the command to run with the modified PATH

In your case, you would use it as follows:

unpath git ./script

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.