find -print0 の出力を printf %b 形式に変換するための小さなユーティリティを D で作成しました。そのようなユーティリティは既に存在します ( 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;
}
差分出力の一部を次に示します。
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 を介した検索の出力にはまだ違いがあります。ただし、これは(ルートとして)実行する場合にも当てはまります
diff <(find / print) <(find / print) > (myhomedirectory)/log.txt
だから私はそれを無視することにしました。