“read” 在 ZSH 中按预期工作,但在使用任何其他 shell 时行为有所不同

“read” 在 ZSH 中按预期工作,但在使用任何其他 shell 时行为有所不同

我已经编写了一个简短的while循环do,但我发现它在不同的 shell 下工作得很奇怪。

就是这样:

find "`pwd`" -type d | while read -r D; do ls ${D}; done

当我使用 启动它时zsh,一切都很顺利。但是,当我使用任何其他 shell 在标题中包含转义字符的任何目录中启动它时,它就会崩溃。

为什么会这样?我尝试使用read -d,但它会忽略任何类型的转义字符,例如 \n。read -r也没有任何事情发生。

答案1

尝试这个: find "$(pwd)" -type d | while read -r D; do ls -lb "${D}"; done

如果只使用一个空字符,ls那么在 bash 中您看到的只是?文件名的 ,例如等于“\n”。在这些情况下
-print0 | xarg -0可能是必要的,并且当 $D 包含空格时不带$D引号可能会导致麻烦。

$ man ls摘抄:

-b,——转义
      打印非图形字符的 C 风格转义符
-l 使用长列表格式


不明智的做法:
例如:$ rm "$(echo -en "\r")"- 允许删除以单个回车符(CR)作为名称的文件。

当然,如果你想摆弄这个:
$ echo "TEST" >"This is a filename with a CR _$(echo -en "\r")_here"
...创建一个文件。

$ rm "This is a filename with a CR _$(echo -en "\r")_here"
...将其删除。

答案2

为什么会这样?

${D}和 相同$D。它将被 shell 替换为变量的内容D。因此,如果D包含Hello World,你的

ls -lb $D

变成

ls -lb Hello World

它将尝试列出 2 个目录HelloWorld(而不是 1 个目录Hello World)。

斯科特已经给了你正确的方法:使用"$D",这将导致

ls -lb "Hello World"

相关内容