「>」に関する警告
I / Oリダイレクト(<
および>
)について学んだばかりのUnix初心者は、しばしば次のようなことを試みます。
コマンド … input_file > the_same_file
または
コマンド …< ファイル > the_same_file
または、ほぼ同等に、
cat ファイル | コマンド …> the_same_file
(grep
、sed
、cut
、sort
、とspell
人々はこのような構築物中で使用するように誘惑されているコマンドの例です。)ユーザーは、これらのシナリオが空になってきてファイルにつながることを発見して驚いています。
他の答えで言及されていないように見えるニュアンスは、bash(1)のRedirectionセクションの最初の文に潜んでいます:
コマンドが実行される前に
、シェルによって解釈される特別な表記を使用して、コマンドの入力と出力がリダイレクトされる場合があります。
コマンドが実行される前にシェルが要求されたリダイレクトを実行するという事実を強調するために、最初の5つの単語は太字、斜体、下線、拡大、点滅、赤、アイコンでマークする必要があります
。そしてまた覚えている
出力のリダイレクトにより、ファイル…が書き込み用に開かれます…。ファイルが存在しない場合は作成されます。存在する場合は、サイズがゼロに切り捨てられます。
したがって、この例では:
sort roster > roster
シェルroster
は、sort
プログラムの実行を開始する前に、書き込み用にファイルを開き、切り捨てます(つまり、その内容をすべて破棄します)。当然、データを回復するために何もできません。
ナイーブにそれを期待するかもしれない
tr "[:upper:]" "[:lower:]" < poem > poem
より良いかもしれません。シェルは左から右へのリダイレクトを処理するため、poem
読み取り用(tr
の標準入力用)に開いてから書き込み用(標準出力用)に開きます。しかし、それは役に立ちません。この一連の操作では2つのファイルハンドルが生成されますが、どちらも同じファイルを指します。シェルが読み取りのためにファイルを開くと、内容はまだ存在しますが、プログラムが実行される前にそれらはまだ破壊されています。
それでは、どうすればいいのでしょうか?
ソリューションが含まれます:
実行しているプログラムに、出力先を指定する独自の内部機能があるかどうかを確認します。多くの場合、これは-o
(または--output=
)トークンで示されます。特に、
sort roster -o roster
とほぼ同等です
sort roster > roster
ただし、最初の場合、sort
プログラムは出力ファイルを開きます。そして、それはまで出力ファイルを開くことがないように十分にスマートだ後、それは、入力ファイル(複数可)のすべてを読みました。
同様に、少なくともいくつかのバージョンがsed
持っている-i
(編集私は戻って、入力ファイルにアウト出力を書き込むために使用することができますn個置き)オプションを(再び、後にすべての入力が読み込まれています)。以下のようなエディタed
/ ex
、emacs
、pico
、およびvi
/はvim
、ユーザーがテキストファイルを編集して、元のファイルに編集したテキストを保存することができます。ed
(少なくとも)非対話的に使用できることに注意してください。
vi
関連機能があります。を入力すると、編集バッファーの内容がに書き込まれ、出力が読み取られ、バッファーに挿入されます(元の内容を置き換えます)。:%!command
Entercommand
シンプルだが効果的:
コマンド … input_file > temp_file && mv temp_file input_file
これにinput_file
は、リンクの場合、(おそらく)別のファイルに置き換えられるという欠点があります。また、新しいファイルはデフォルトの保護で所有されます。特に、これは、元のファイルがそうでなくても、ファイルが最終的に誰でも読み取り可能になるというリスクを伴いますinput_file
。
バリエーション:
command … input_file > temp_file && cp temp_file input_file && rm temp_file
これにより、(潜在的に)誰でもtemp_file
読み取り可能になります。さらに良い:
cp input_file temp_file && command … temp_file > input_file && rm temp_file
これらは、ファイルのリンクステータス、所有者、モード(保護)を保持しますが、I / Oが2倍になる可能性があります。(次のようなオプションを使用する必要があるかもしれません-a
か、-p
上のcp
属性を保持するためにそれを伝えるために。)
command … input_file > temp_file &&
cp --attributes-only --preserve=all input_file temp_file &&
mv temp_file input_file
(読みやすくするために別々の行に分けています)これにより、ファイルのモード(および、rootの場合は所有者)は保持されますが、所有者(rootでない場合)になり、新しいファイルになります。別のファイル。
このブログ
(ファイルの「インプレース」編集)は、提案と説明を行います
{rm input_file && command …> input_file ; } < input_file
これには、command
標準入力を処理できる必要があります(ただし、ほとんどすべてのフィルターが処理できます)。ブログ自体はこれを危険な手口と呼び、その使用を推奨していません。また、これにより、ユーザーが所有し、デフォルトのアクセス権を持つ新しい別個のファイル(何にもリンクされていない)が作成されます。
moreutilsパッケージには、次のコマンドがありますsponge
。
コマンド … input_file | スポンジthe_same_file
詳細については、この回答を参照してください。
私にとって完全な驚きとして来たもの
は次のとおりです。
[これらのソリューションのほとんどは、「読み取り専用」あなたのことを意味し、読み取り専用ファイルシステム上で失敗し$HOME
ます書き込み可能ではなく、/tmp
される読み取り専用(デフォルト)。たとえば、Ubuntuがあり、回復コンソールを起動した場合、これは一般的なケースです。また、ヒアドキュメント演算子<<<
も
一時ファイルをそこに書き込むため、読み取り/書き込み/tmp
が必要なため、ここでも動作しません。
(この質問には「d」の出力が含まれます)
strace
その場合、以下が機能する可能性があります。
それで、質問は何でしたか?
これはU&Lで人気のあるトピックです。次の質問で対処します。
…そしてそれはスーパーユーザーやUbuntuを数えていません。上記の質問に対する回答の多くの情報をこの回答に取り入れましたが、すべてではありません。(つまり、詳細については、上記の質問とその回答をお読みください。)
PS私は、上で引用したブログと提携していません。