2

(I'm using bash 3.2 in the Terminal app on OS X 10.11.4.)

I have this line in my .bashrc file: alias ll='ls -alFh'

I ran echo ll > test && chmod +x test to create a test executable. Below are the results of running multiple commands, their exit codes (via echo $?), and stdout:

  1. test
    exit code 1
    produces no stdout

  2. ./test
    exit code 127
    produces ./test: line 1: ll: command not found

  3. . test
    exit code 127
    produces -bash: ????: command not found

  4. . ./test
    exit code 0
    produces identical result to manually running ll

I understand that exit code 1 is a generic error and that exit code 127 means the shell can't find the command. Will someone please explain what is happening in each of these cases and why, including a description of the stdout? I am especially confused at #3 with the ????.

Community
  • 1
  • 1
jsejcksn
  • 27,667
  • 4
  • 38
  • 62
  • @sjsam I perused many links from multiple similar searches already and found nothing pertinent to #3 before posting this question. – jsejcksn May 07 '16 at 11:35
  • For the record, my path is fine. @sjsam the downvote is not necessary—you obviously did not fully read my question and compare it to any of the results you linked to. – jsejcksn May 07 '16 at 11:38
  • What happens if - you create the `test`,close the terminal, start a new terminal session and execute the commands in the order you have given? – sjsam May 07 '16 at 11:52
  • @sjsam The results are identical. – jsejcksn May 07 '16 at 11:53
  • I tried this and couldn't reproduce it. I don't know where that ???? is coming from for you. – Steve Summit May 07 '16 at 11:58
  • This happened probably because the current shell session was initiated with an old version of .bashrc . You might add a `shebang` to `test` to resolve case 2 I guess.. You might use `type ll` to check if aliases are in working. – sjsam May 07 '16 at 12:01
  • @sjsam I duplicated the file as `test2` and added `#!/bin/bash` as the shebang and still no difference. – jsejcksn May 07 '16 at 12:10

1 Answers1

4

First you run:

echo ll > test && chmod +x test

then these cases.

Case 3:

When you execute:

. test

it is equivalent of:

source test

source is a shell builtin that tells the shell to read the given script file and execute the commands in the current shell environment. However since current path or . is not in your path, it finds test using PATH environment variable which is /bin/test.

/bin/test is not really a script file that can be read/executed by source; it ends up reading a binary file and errors out since that file is a binary file, not an ascii text file and errors out writing:

????: command not found

You will get same behavior when you run source date or source ls as these are all binary files.

Case 1:

You are executing shell builtin test without any arguments that makes it exits with exit value: 1

Case 2:

When you run ./test it attempts to run ll and alias is not available in spawned sub-shell hence it cannot find alias ll. Due to that fact it exits with exit value: 127 with ./test: line 1: ll: command not found error on stderr.

Case 4:

. ./test is same as source ./test that run in current shell only. Therefore it is able to find alias you've set earlier for ll hence it runs aliased command ls -alFh and exits with 0

tripleee
  • 175,061
  • 34
  • 275
  • 318
anubhava
  • 761,203
  • 64
  • 569
  • 643
  • This partly addresses #3, but it doesn't answer my question: an explanation for each of them. It also doesn't cover the reason for the `????` in the output (for example, vs `-bash: test: command not found`) – jsejcksn May 07 '16 at 11:59
  • It does explain reason of `???? in the output` (reading **binary** file `/bin/test`) – anubhava May 07 '16 at 12:02
  • When I run another command that doesn't exist, say `marcopolo` for example, I get `-bash: marcopolo: command not found` (exit code 127). – jsejcksn May 07 '16 at 12:04
  • Yes because `marcopolo` doesn't exist. Try running `source date` or `source ls` to see same behavior. – anubhava May 07 '16 at 12:05
  • I see what you mean with the `????` now. Case 4 DOES succeed, though. In your answer you are saying that it doesn't, but re-read my question. – jsejcksn May 07 '16 at 12:11
  • Also, why isn't Case 2 a valid executable? I'd like a longer form explanation or links to some documentation. This information is not enough to help me understand what is happening or what problems exist. – jsejcksn May 07 '16 at 12:13
  • First of all there should be one question per SO thread. I replied but hope you appreciate it. case 2 is not a valid executable because `./test` means **try to run test in current directory**. Finally `. ./test; echo $?` will indeed exit with `1` as my answer says. Your question is not correct on case #4 – anubhava May 07 '16 at 12:17
  • I do appreciate your responding, but what you're saying about case 4 is simply not correct—it does succeed and exits with code 0. Are you testing on OS X? – jsejcksn May 07 '16 at 12:24
  • I don't think your demo is right because it doesn't contain the .bashrc or executable created in the steps leading up to the question. – jsejcksn May 07 '16 at 12:31
  • Thanks for the update. It is starting to make more sense now. I still don't understand the difference between case 3 and 4. Why does it find `/bin/test` in case 3 and not the `test` file I made, and in case 4 why does it find the `test` file I made and not `/bin/test`? – jsejcksn May 07 '16 at 13:05
  • Actually I wrote the reason of that in my answer. When you run `source test` it won't find `test` file in your current directory because `.` (DOT) is not included in your `PATH` variable hence it finds `/bin/test` since `/bin/` is in the path. Case 4 is different because you're using `./test` which **means run test from current directory** and then it won't even check the PATH – anubhava May 07 '16 at 13:09
  • I understand what is happening, but I don't understand why. Does the path always receive priority over specifying a file in the current directory without a leading path? (ex. `source file` vs `source ./file`) Is this only true with the `source` command or is it true with other commands, too? (ex. `rm file` vs `rm ./file`) – jsejcksn May 07 '16 at 13:16
  • PATH is not even checked when you invoke it as `./test` (which means run `test` from current directory). Only when you don't provide any path before `test` like `source test` then only path is checked. Please try to spend some time on reading unix paths resolution outside this question. – anubhava May 07 '16 at 13:21
  • 1
    Great—that's the kind of information I needed. Thanks! – jsejcksn May 07 '16 at 13:28