带有unicode文件路径的runco​​mmand(haskell)

时间:2013-07-05 12:47:12

标签: bash haskell unicode normalization unicode-normalization

我想从Haskell运行一个带有unicode文件路径的bash命令。

Haskell中的字符串使用\ escapes,例如

"beißen" -> "bei\223en"

Bash似乎接受以下格式:

$'bei\xC3\x9Fen.avi''beißen.avi'

因为runCommand中的System.Process具有类型

runCommand :: String -> IO System.Process.Internals.ProcessHandle

如何将Haskell字符串编码为Bash接受的格式之一?

使用具有bash 3.2的Mac OSX 10.8.4。

修改

我的问题似乎与bash转义有关

我使用Text.ShellEscapehttp://hackage.haskell.org/packages/archive/shell-escape/0.1.2/doc/html/Text-ShellEscape.html)来逃避需要为bash转义的字符

e.g

import qualified Data.ByteString.Char8 as B
import qualified Text.ShellEscape as Esc
let cmd = B.unpack $  Esc.bytes    $  Esc.bash . B.pack $ "beißen.txt"

给了我"$'bei\\xDFen.txt'"

运行runCommand $ "ls " ++ cmd

时 它给了我 ls: bei�en.txt: No such file or directory

有一种更好的方法可以为bash转义字符串吗?

1 个答案:

答案 0 :(得分:4)

如果你想处理非ASCII文本,

Data.ByteString.Char8几乎永远不是正确的选择。它会破坏你的数据。在您的情况下,您可能应该使用Data.ByteString.UTF8代替(假设您使用UTF-8语言环境,大多数现代桌面Unix-y操作系统就是这种情况)。

Data.ByteString.Char8修改数据的示例:

Prelude Data.ByteString.Char8> "été"
"e\769te\769"
Prelude Data.ByteString.Char8> unpack $ pack "été"
"e\SOHte\SOH"
Prelude Data.ByteString.Char8> Prelude.putStrLn "été"
été
Prelude Data.ByteString.Char8> Prelude.putStrLn $ unpack $ pack "été"
ete

使用Data.ByteString.UTF8.toString而非Data.ByteString.Char8.unpack

这些调用

let s = toString $ bytes $ bash $ fromString "мама.sh"
runCommand s
runCommand $ "ls -l " ++ s

在ghci中为我工作("мама.sh"是一个shell脚本,名称中包含一些西里尔字符)。

当然,如果你逃避整个命令,它也会逃离空白区域,它将无法正常工作。单独逃避命令的每个单词。