我在 D 中编写了一个小实用程序,用于将 find -print0 的输出转换为 printf %b 格式。这样的实用程序已经存在(来自http://www.dwheeler.com/essays/filenames-in-shell.html的 nul2pfb ),但是链接已失效,我找不到该程序,所以我决定自己实现它D. 我正在使用以下 zsh 命令进行测试:
diff <(find) <(for i in "$(find -print0 | dd | char2code)"; do printf '%b\n' "$i"; done)
预期的输出为空,但我发现某些包含连字符的文件名处理错误。
我的源代码是这样的:
import std.stdio;
import std.conv;
import std.ascii;
import std.c.stdlib;
void main()
{
foreach (ubyte[] mybuff; chunks(stdin, 4096)) {
encodeline (mybuff);
}
}
@safe void encodeline (ubyte[] mybuff) {
// char[] outstring;
foreach (ubyte i; mybuff) {
char b = to!char(i);
switch (i) {
case 'a': .. case 'z':
case 'A': .. case 'Z':
case '0': .. case '9':
case '/':
case '.':
case '_':
case ':': writeChar(b); break;
default: writeOctal(b); break;
case 0: writeChar ('\n'); break;
case '\\': writeString(`\\`); break;
case '\t': writeString(`\t`); break;
case '\n': writeString(`\n`); break;
case '\r': writeString(`\r`); break;
case '\f': writeString(`\f`); break;
case '\v': writeString(`\v`); break;
case '\a': writeString(`\a`); break;
case '\b': writeString(`\b`); break;
}
}
// writeString (outstring);
}
@trusted void writeString (string a)
{
write (a);
}
@trusted void writeOctal (int a)
{
try
{
writef ("\\%.#o", a); // leading 0 needed for for zsh printf '%b'
}
catch (std.format.FormatException b)
{
write ("Format exception in function writeOctal");
throw b;
}
}
@trusted void writeChar (char a)
{
try
{
write (a);
}
catch (std.format.FormatException b)
{
write ("Format exception in function writeChar");
throw b;
}
}
@trusted void writeNewline ()
{
writeln;
}
这是 diff 输出的一部分:
Correct filenames:
./.ibam/profile-004-battery
./.ibam/profile-034-charge
./.ibam/profile-054-charge
./.ibam/profile-045-battery
(a bunch of lines skipped)
---
Wrong filenames:
./.ibam/profileh04-battery
./.ibam/profileh34-charge
./.ibam/profileh54-charge
./.ibam/profileh45-battery
似乎 -0 正在被 h 取代。
更新:在 writef 的转换说明符中将 .# 替换为 .4 解决了问题,但我仍然看到通过 /proc 搜索的输出存在差异。但是,当我这样做时也是如此(以root身份)
diff <(find / print) <(find / print) > (myhomedirectory)/log.txt
所以我选择忽略它。