0

In my scripts I have a function called messages. I wrote it in Linux Mint, with no problems running it, and when I moved it to a Debian Buster station, the function clashes with /usr/bin/messages.

I have a startup script that calls the script messages:

startup_script

# call to messages script
. messages

messages

messages() {
  # reformat the arguments and return them
}

later on startup_script

messages "This is a message"

Which throws

./startup_script: line 35: .: /usr/bin/messages: cannot execute binary file
messages: could not open mailbox `/path/to/my/script/<string passed to my function>': No such file or directory

So I get a bunch of errors related to /usr/bin/messages being called instead of my function.

After adding type messages "This is a message", the relevant output is:

messages is /usr/bin/messages

I have the option of renaming my function¹, but maybe there's a better way to handle this situation.

How do I tell my script to ignore system binaries and use my own functions?


¹ The function is called in several scripts, many times, so it is not the easiest option to just change the name.

6
  • 1
    add type messages, before messages "This is a message". What output do you get? Commented Mar 10, 2020 at 23:12
  • @ctrl-alt-delor Updated the question, but basically messages is /usr/bin/messages. Commented Mar 10, 2020 at 23:19
  • At the point you think you're calling your own messages function, it has not been defined. Commented Mar 10, 2020 at 23:22
  • Sorry guys, it's indeed the calling of the script the problem ". messages" (I'll find out why it doesn't work). Thanks for your time! I have done this "movings" to another OSs and didn't have this problem Commented Mar 10, 2020 at 23:28
  • As I have the scripts all in the same folder, I just call them ". script", to circumvent this I have to put the full path ". /path/script". Commented Mar 10, 2020 at 23:33

2 Answers 2

6

This is how . file works:

If file does not contain a <slash>, the shell shall use the search path specified by PATH to find the directory containing file.

This behavior is specified by POSIX.

Your first error is

./startup_script: line 35: .: /usr/bin/messages: cannot execute binary file

It's similar when you call . echo:

-bash: .: /bin/echo: cannot execute binary file

You're trying to source the binary file /usr/bin/messages. In effect your file where the function is defined is not sourced at all, the function is not defined in the current script. This means later messages still means /usr/bin/messages, not the function.

The relevant line should be . ./messages or . /full/path/to/messages (i.e. path to your file, not to the binary).

3
  • 1
    Ah, gotcha - the executable takes precedence over the current directory +1 Commented Mar 10, 2020 at 23:29
  • Brilliant !my internet is slooooww so I couldn't see this before I commented. Thanks! Commented Mar 10, 2020 at 23:36
  • It may be useful to note that Bash doesn't strictly enforce the POSIX "dot" builtin spec by default and successfully sources file from the current working directory if no file in found in PATH. (This, combined with . not requiring file to be executable, is probably a source of confusion, leading people to forget about the PATH search part).
    – fra-san
    Commented Mar 11, 2020 at 11:47
1

Interpreting error messages

Look at the line number in the error message. That way you will know which line the error is on. That was hidden from us, as you showed us a few line from a script containing over 35 lines.

What file is executed.

When you specify a file with . file-to-source or file-to-run, the directories listed in the environment variable $PATH are searched left to right. The current directory is not in this list, as it can be a security risk, or at least be of confusion. It run a program in the current directory you have to specify that it is in the current directory. e.g. . ./file-to-source or ./file-to-run (There is no need to give full path).

Unixes used to have . in the PATH, until it was realised that this was a problem. E.g. put a program called ls in the current directory. CMD in Microsoft's Windows still has . implicitly in the PATH, you can't remove it. It is one of the causes of high mall-ware, on this OS.

A gotcha

. refers to the current working directory not to the directory that the script is in.

To solve that then something like this can be done.

(
   cd "$(dirname "$(readlink -f "$0")")"
   script_dir="$(pwd)"
)
script_dir/other_script

Hopefully someone can link to a better solution.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .