![“read” 在 ZSH 中按预期工作,但在使用任何其他 shell 时行为有所不同](https://linux22.com/image/1463969/%E2%80%9Cread%E2%80%9D%20%E5%9C%A8%20ZSH%20%E4%B8%AD%E6%8C%89%E9%A2%84%E6%9C%9F%E5%B7%A5%E4%BD%9C%EF%BC%8C%E4%BD%86%E5%9C%A8%E4%BD%BF%E7%94%A8%E4%BB%BB%E4%BD%95%E5%85%B6%E4%BB%96%20shell%20%E6%97%B6%E8%A1%8C%E4%B8%BA%E6%9C%89%E6%89%80%E4%B8%8D%E5%90%8C.png)
我已经编写了一个简短的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 个目录Hello
和World
(而不是 1 个目录Hello World
)。
斯科特已经给了你正确的方法:使用"$D"
,这将导致
ls -lb "Hello World"