ファイルを使用する前に削除したいので、この例ではpaste
始める前にcol1、col2 ... col1000のリンクを解除したいと思います。
exec 3< col1 4< col2 ... 1002< col1000
rm col1 col2 ... col1000
paste /dev/fd/3 /dev/fd/4 ... /dev/fd/1002
これはGNU / Linux + bashでうまく機能します。ただし、/dev/fd/X
他のシステムに移植することはできません。
私が使用できるbash
コマンドの置き換えは次のとおりです。
exec 3< col1 4< col2 ... 1002< col1000
rm col1 col2 ... col1000
paste <(cat <&3) <(cat <&4) ... <(cat <&1002)
ただし、これを行うにはファイルごとに1つのプロセスが必要です。
すべてのシステムでBashと連携するように上記の内容を書くことはできますか?たぶん特別なBash構文がありますか?
ベストアンサー1
最も簡単な移植可能な解決策は、ファイル記述子番号を引数として使用し、ファイルpaste
記述子リダイレクトを含む組み込み関数を使用してそれを繰り返す関数に置き換えることです。read
paste()
{
at_least_one_read_succeeded=true
while $at_least_one_read_succeeded
do
at_least_one_read_succeeded=false
first_fd=true
for fd in "$@"
do
if ! $first_fd
then
printf '\t'
fi
if IFS= read -r line <&"$fd"
then
at_least_one_read_succeeded=true
fi
printf '%s' "$line"
first_fd=false
done
printf '\n'
done
}
主な欠点は、シェルの組み込み機能が別々のシステムコールをread
実行するしかないため、速度がはるかに遅いことです。read
バイトごとに。同様にprintf
、コマンドを呼び出すたびに少なくとも1つのwrite
システムコールを実行する必要があります(理論的には、最適化コンパイラとJIT VMが実行するのと同じ分析を使用して、この場合I / Oを最適化できるシェルを作成できます。 )。しかし、現在そのようなシェルは存在しません)。ほとんどの場合、最新のハードウェアではその違いはまだ無視できますが、例には何千ものファイルが含まれているため、実際にパフォーマンスが低下する可能性があり、これはユースケースにとって重要です。
もちろん、時間と労力を尊重することに加えて、シェルで独自にバッファリングされたI / Oをローリングするのを防ぐ方法はありません。たとえば、dd bs=4096 count=1
一度に4096バイトを各FDの別々の変数として読み込み、改行が不足するまでその行をインポートできます。たとえば、という bash 配列を作成し、buffers
次のようにbuffers[$fd]=$(dd bs=4096 count=1 <$&fd)
読み取ることができます。${buffers[$fd]%%'$\n'*}
正直に言うと、これを検討していてcol
これらのファイルをディスクに保存しないことが非常に重要な場合は、これらの列ファイルの内容全体を変数として読み取ることも検討できますbash
。データサイズはわかりません。しかし、システムがbash
その程度の割り当てを許可し、それbash
自体を処理する場合本物これらのファイルがディスクに残らないようにすることも重要ですが、コンテンツが指定されたファイルにまったく届かないようにすることも十分に重要です。
しかし、一歩後ろに退ければ、これほど十分ではないでしょうか?
paste col1 col2 ... col1000 & # background `paste`
# optionally, put a tiny sleep here
rm col1 col2 ... col1000
wait # wait for `paste` to finish
col*
正直なところ、ファイルがクリーンアップされない時間が常にあるからです(rm
コードまたは以前に実行されていたコードにrm
停電が発生した場合はどうなりますかpaste
?)。ウィンドウが起動し、システムコールを介してすべてのパラメータに到達したpaste
ときにウィンドウが<= 1秒間持続する場合(最新のハードウェアでは1ミリ秒未満で十分です)、本当に悪いですか?open
考慮すべきもう一つのことは、一時ファイルシステムを使用することです。多くのオペレーティングシステムは、特定のパスにメモリ内ファイルシステムを提供します。たとえば、ほぼすべてのLinuxディストリビューションには、通常、各ユーザーが個人用ディレクトリを取得するマウントポイントが/run
あります。電源がオフになったり、ボックスを再起動またはシャットダウンしたりすると、その中のすべての項目は保存されません。実行する必要がある他のシステムが何であるかはわかりませんが、そのシステムに一時メモリファイルシステムがあるかどうか、または再起動時にOSディレクトリによってクリアされることが保証されていることを確認することをお勧めします。tmpfs
/run/$(id -u)
tmpfs