How can I track script which gives me "command not found" right after the login?

Bash reads a number of different files on startup, even depending on how it's started (see the manual for the description). Then there's stuff like /etc/profile.d/ that aren't directly read by the shell, but can be referenced from the other startup files in many distributions.

You'll have to go through all of those but luckily, you can just grep for the carriage return. Try e.g. something like:

grep $'\r' ~/.bashrc ~/.profile ~/.bash_login ~/.bash_profile /etc/bash.bashrc /etc/profile /etc/profile.d/*

See also Is it possible to find out which files are setting/adding to environment variables, and their order of precedence? for a similar issue.


file(1) can be helpful here as well.

$file *

signin:                                     Python script, ASCII text
signup:                                     Python script, ASCII text, with CRLF line terminators
site_off.htm:                               XML 1.0 document, ASCII text
sitemaps:                                   directory

I can see that signup needs to have those pesky Windows CRLF line-endings removed.

For a recursive directly like /home/username you could probably combine with find and xargs (and maybe a grep, too):

$ find . | xargs file | grep CR

./foo_data/V: ASCII text, with CR, LF line terminators
./foo_data/Y: ASCII text, with CR, LF line terminators

Another method is to take all of those startup scripts mentioned, and echo a string identifying each one at the start of each one.

$ head .bashrc
echo "Running bashrc"

Then, on login, you will see something like this:

running bashrc
running bash_aliases
-bash: $'\r' : command not found
-bash: $'\r' : command not found
-bash: $'\r' : command not found 
running something_else

At that point you can conclude that, (in the example above) .bash_aliases contains the offending line endings.

Once you have identified the file, but the problem lines don't jump out at you, you can use the same method to track down the line. Echo a message halfway through the file, then 3/4ths or 1/4s through, depending on the output. That way you can track down the line, depending on whether it echoes before or after your echo.