【问题标题】:bash test yields "echo: command not found"bash 测试产生“回声:找不到命令”
【发布时间】:2011-03-21 17:44:00
【问题描述】:

好吧,突然发生了一些有趣的事情。本次测试

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

以前可以正常工作(对于文件 liste.txt 中的每个条目,尝试查找相应的目录,如果找不到则打印名称)并用于生成丢失的目录名称。现在这个命令产生

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

我尝试使用 [[...]] 和 "test" 而不是 "[ ..]" 但无济于事。

有什么想法在我不注意的时候与我心爱的 bash 发生了什么:)?

谢谢, 克里斯蒂安。

编辑(设置 -x 输出):

(...)
+ 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
(...)

【问题讨论】:

  • 你有没有尝试双引号 $i ?
  • 如果将行尾替换为echooooo $1; done,是否会报错echooooo: command not found?当我在 bash 命令提示符下键入 junk 时,我得到了“找不到命令”错误。如果换成/bin/echo会怎样?
  • 将set -x 添加到脚本的顶部并观察shell 执行的每个命令。
  • 我的发现:双引号 $i:无济于事,同样的错误。 echoooo:找不到命令。

标签: bash testing command echo


【解决方案1】:

如果你仔细观察,你会看到它正在打印:

 echo: command not found

前导空格,而不是:

echo: command not found

set -x 在打印时更清楚:

$'\302\240echo' THE_REBOUND

0302 0240 是 non-breaking space 的八进制 UTF-8。

尝试删除| 和echo 之间的空格并键入一个普通空格。


很有可能,该文件是在 Mac 上编辑的,如果同时按 Option 和 Space,可能会意外输入不间断空格。

如果您使用 Vim,则可以使用 listchars option 使不间断空格更加明显。例如:

set listchars+=nbsp:% list

更多想法请见Making Vim highlight suspicious characters。

在 Linux 上,不间断空格是 Compose Space Space 或 Ctrl+Shift +ua0,所以你可能不会意外输入。


对于任何感兴趣的人,都可以使用 UTF-8 维基百科文章中的 UTF-8 table 手动将八进制字节转换为 UTF-8。

但到目前为止,我发现最简单的方法是使用 Python:

>>> import unicodedata
>>> unicodedata.name('\302\240'.decode('utf-8'))
'NO-BREAK SPACE'

【讨论】:

    【解决方案2】:

    编辑:下面的代码仍然可以,但问题可能出在$'\302\240echo':您的文本文件中似乎有未知字符。尝试在 echo 之前删除这两个字符,然后再次输入。

    这很可能是一个引用的问题。此外,您可以通过避免使用useless use of cat 来节省一些时间:

    while IFS= read -r; do [ -f "/mnt/usb/lsdvd.xml/$REPLY" ] || echo "$REPLY"; done < /mnt/usb/liste.txt
    

    【讨论】:

      【解决方案3】:

      当你简单地运行时会发生什么:

      for i in `cat /mnt/usb/liste.txt `; do
          echo $i
      done
      

      一方面,您是否注意到文件名有任何异常(空格、换行符、特殊字符等)?如果是这样,您将需要引用文件名以防止 shell 误解它。

      另外,尝试使用普通的if 语句而不是逻辑 OR:

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

      【讨论】:

      • 简单的 for-echo-done 循环工作正常,文件名没有什么异常。实际上,它们非常好:没有空格,没有偶数。
      • for-if-then-fi-done 循环工作正常,所以它一定是关于 ||和奇怪的未加引号的字符串,但我似乎找不到关于文件及其名称的任何异常。
      【解决方案4】:

      为我工作:

      for f in $(< d2.lst); do [ -f ./d2/$f ] || echo $f ; done
      

      只是我自己的文件名、目录和建议的构造 $(...) 而不是反引号,并用

      也许你的列表中有一个 dos/windows 换行符?使用less 查看。

      【讨论】:

        猜你喜欢
        • 2015-08-03
        • 2013-12-07
        • 2017-04-14
        • 1970-01-01
        • 2016-09-02
        • 1970-01-01
        • 2012-03-06
        • 2020-03-11
        • 2013-03-01
        相关资源
        最近更新 更多