You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何echo命令读取含CRLF的文件中的*时不列出目录内容?

问题背景

先来看下两个文件的基本情况:

  • file1.txt(Linux系统创建):
    root@localhost:~# file file1.txt
    file1.txt: ASCII text
    root@localhost:~# od -c file1.txt
    0000000  *  \n
    
  • file2.txt(Windows系统创建):
    root@localhost:~# file file2.txt
    file1.txt: ASCII text, with CRLF line terminators
    root@localhost:~# od -c file2.txt
    0000000  *  \r  \n
    

执行一系列命令后出现了令人困惑的差异:

root@localhost:~# ls
myFile1 myFile2 myFile3
root@localhost:~# echo `cat file1.txt`
myFile1 myFile2 myFile3
root@localhost:~# echo `cat file2.txt`
*
问题解答

这个现象的核心是Shell命令替换的规则和回车符(\r)的特殊影响,咱们一步步拆解:

  1. 先搞懂命令替换的本质
    当你用`cat file.txt`这种反引号语法时,Shell会先执行cat命令读取文件内容,把这个内容替换到echo命令的参数位置,再执行最终的echo。

  2. file1.txt的正常流程
    file1.txt的内容是*\n(星号加换行),Shell做命令替换时,会把末尾的换行符\n当成空白分隔符处理,最终echo的参数就只剩*。而Shell在执行echo前会做路径扩展(globbing)——也就是把*展开成当前目录下所有非隐藏文件的名字,所以最终输出了myFile1 myFile2 myFile3。

  3. file2.txt的问题出在\r上
    file2.txt的内容是*\r\n(星号加回车加换行),这里的\r(回车符)是关键:

  • 命令替换时,Shell会自动去掉末尾的\n,但\r会被保留下来,所以替换后echo的参数是*\r(星号加不可见的回车符)。
  • 此时*后面跟着的\r被Shell当成了普通字符,而不是空白分隔符。这就导致*\r变成了一个完整的字符串,不再是独立的通配符*。
  • Shell的路径扩展只会匹配完全符合通配符规则的内容,当前目录里没有任何文件名包含\r,所以*\r无法匹配到任何文件,通配符不会被展开。最终echo直接输出*(\r是控制字符,终端输出时会把光标移到行首,但因为后面没有其他字符覆盖,所以你看到的就只有*)。

简单来说:Windows系统的CRLF换行带来的\r字符,破坏了Shell对通配符*的识别,让它从“匹配所有文件的通配符”变成了一个带隐藏字符的普通字符串,自然就不会展开成目录里的文件了。

内容的提问来源于stack exchange,提问作者kozooh

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.29 07:36:03