Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

bash test yields "echo: command not found"

Ok, something funny happens all of a sudden. This test

for i in `cat /mnt/usb/liste.txt `; do [ -f /mnt/usb/lsdvd.xml/$i ] || echo $i; done

used to work fine (for every entry in the file liste.txt try to find a corresponding directory, print the name if not found) and used to yield the names of directories missing. Now this command yields

 echo: command not found
 echo: command not found
 echo: command not found
(...)

I've tried using [[...]] and "test" instead of "[ ..]" but to no avail.

Any ideas what might have happened with my beloved bash while I wasn't looking :) ?

Thanks, Christian.

Edit (set -x output):

(...)
+ for i in '`cat /mnt/usb/liste.txt`'
+ '[' -f /mnt/usb/lsdvd.xml/THE_GHOST_WRITER.lsdvd.xml ']'
+ for i in '`cat /mnt/usb/liste.txt`'
+ '[' -f /mnt/usb/lsdvd.xml/THE_IMAGINARIUM_OF_DOCTOR_PARNASSUS.lsdvd.xml ']'
+ for i in '`cat /mnt/usb/liste.txt`'
+ '[' -f /mnt/usb/lsdvd.xml/THE_INFORMANT.lsdvd.xml ']'
+ for i in '`cat /mnt/usb/liste.txt`'
+ '[' -f /mnt/usb/lsdvd.xml/THE_INTERNATIONAL.lsdvd.xml ']'
+ for i in '`cat /mnt/usb/liste.txt`'
+ '[' -f /mnt/usb/lsdvd.xml/THE_MEN_WHO_STARE_AT_GOATS.lsdvd.xml ']'
+ for i in '`cat /mnt/usb/liste.txt`'
+ '[' -f /mnt/usb/lsdvd.xml/THE_OTHER_MAN.lsdvd.xml ']'
+ for i in '`cat /mnt/usb/liste.txt`'
+ '[' -f /mnt/usb/lsdvd.xml/THE_QUEEN.lsdvd.xml ']'
+ for i in '`cat /mnt/usb/liste.txt`'
+ '[' -f /mnt/usb/lsdvd.xml/THE_READER.lsdvd.xml ']'
+ for i in '`cat /mnt/usb/liste.txt`'
+ '[' -f /mnt/usb/lsdvd.xml/THE_REBOUND.lsdvd.xml ']'
+ $'\302\240echo' THE_REBOUND
+ '[' -x /usr/lib/command-not-found ']'
+ /usr/bin/python /usr/lib/command-not-found -- $'\302\240echo'
 echo: command not found
+ return 127
(...)
like image 526
Christian Avatar asked Mar 21 '11 17:03

Christian


2 Answers

If you look closely, you will see it's printing:

 echo: command not found

with a leading space, rather than:

echo: command not found

set -x makes this much clearer when it prints:

$'\302\240echo' THE_REBOUND

0302 0240 is octal UTF-8 for a non-breaking space.

Try deleting the space between | and echo and type a normal space.


Chances are, the file was edited on a Mac, where a non-breaking space can be entered accidentally if you press Option at the same time as Space.

If you're using Vim, you can make non-breaking spaces more obvious by using the listchars option. For example:

set listchars+=nbsp:% list

See Making Vim highlight suspicious characters for some more ideas.

On Linux, non-breaking space is either Compose Space Space or Ctrl+Shift+ua0, so you're probably not going to type that by accident.


For anyone interested, it's possible to manually convert the octal bytes to UTF-8 using the UTF-8 table from the UTF-8 Wikipedia article.

But by far the easiest way I found was using Python:

>>> import unicodedata
>>> unicodedata.name('\302\240'.decode('utf-8'))
'NO-BREAK SPACE'
like image 86
Mikel Avatar answered Oct 05 '22 23:10

Mikel


Edit: The code below is still fine, but the issue is probably in $'\302\240echo': There seems to be unknown characters in your text file. Try removing the couple characters before echo and then typing them again.

It could well be a quoting issue. Also, you could save some time by avoiding the useless use of cat:

while IFS= read -r; do [ -f "/mnt/usb/lsdvd.xml/$REPLY" ] || echo "$REPLY"; done < /mnt/usb/liste.txt
like image 20
l0b0 Avatar answered Oct 05 '22 22:10

l0b0