Neden bir dosyanın çıktısını kendisine yeniden yönlendirmek boş bir dosya üretir?


19

Neden bir dosyanın çıktısını kendisine yeniden yönlendirmek boş bir dosya üretir?

Bash'de belirtin, neden

less foo.txt > foo.txt

ve

fold foo.txt > foo.txt

boş üretmek foo.txt? Gibi bir ek less eggs.py >> eggs.py, içindeki metnin iki kopyasını ürettiğinden eggs.py, üzerine yazma işleminin metnin bir kopyasını üretmesi beklenebilir.

Not, bunun bir hata olduğunu söylemiyorum, büyük olasılıkla Unix hakkında derin bir şeye işaretçi.


U & L'nin standart kurallarında ele alınmıştır Kabuğun kontrol ve yönlendirme operatörleri nelerdir? soru.
Scott

Yanıtlar:


20

Kullandığınızda >, dosya kesme modunda açılır, böylece komut okumayı denemeden önce içeriği kaldırılır.

Kullandığınızda >>, dosya ekleme modunda açılır, böylece mevcut veriler korunur. Ancak yine de bu durumda girdi ve çıktı ile aynı dosyayı kullanmak oldukça risklidir. Dosya, okuma giriş arabelleği boyutuna sığmayacak kadar büyükse, dosya sistemi dolana (veya disk kotanıza ulaşılana kadar) boyutu süresiz olarak büyüyebilir.

Bir dosyayı, yerinde değişiklik yapılmasını desteklemeyen bir komutla hem girdi hem de çıktı olarak kullanmak isterseniz, birkaç geçici çözüm kullanabilirsiniz:

  • Bir aracı dosyası kullanın ve bittiğinde ve yalnızca yardımcı programı çalıştırırken herhangi bir hata oluşmadıysa orijinal dosyanın üzerine yazın (bu en güvenli ve en yaygın yoldur).

    fold foo.txt > fold.txt.$$ && mv fold.txt.$$ foo.txt
  • Bir hata veya kesinti olması durumunda, aradaki dosyayı olası kısmi veya tam veri kaybı pahasına kullanmaktan kaçının. Bu örnekte, içeriği silinmeden öncefoo.txt bir alt kabuğa giriş olarak (parantez içinde) aktarılır . Alt kabuk veri okunurken açık kaldığı için önceki inode canlı kalır. Aynı ada sahipken iç yardımcı program tarafından yazılan dosya (burada )foldfoo.txt), eski dizin girişi teknik olarak kaldırıldığı için farklı bir inode işaret ediyor, işlem sırasında aynı ada sahip iki farklı "dosya" var. Alt kabuk sona erdiğinde, eski inode serbest bırakılır ve verileri kaybolur. Hem eski dosyayı hem de yenisini aynı anda geçici olarak depolamak için yeterli alanınız olduğundan emin olun, aksi takdirde veri kaybedersiniz.

    (rm foo.txt; fold > foo.txt) < foo.txt

3
spongedan moreutils da yardımcı olabilir. fold foo.txt | sponge foo.txt- ya fold foo.txt | sponge !$da yapmalı.
slhck

@slhck Gerçekten, sünger de işi yapabilirdi. Bununla birlikte, ne POSIX tarafından ne de Unix'te OS'ler gibi ana akım olarak belirtilmediğinden, mevcut olması olası değildir.
jlliagre

O olamaz değil ki yapılmış olsa mevcut;)
slhck

7

Uygulama, dosyayı okuma şansına sahip olmadan önce kabuk tarafından yazmak için açılır. Dosyayı yazmak için açmak dosyayı keser.


0

Bash'de, akış yeniden yönlendirme operatörü sol işleneni değerlendirmeden önce... > foo.txt boşalır .foo.txt

Komut ikamesi kullanılabilir ve bir geçici çözüm olarak sonucu yazdırılabilir. Bu çözüm diğer yanıtlardan daha az ek karakter gerektirir:

printf "%s\n" "$(less foo.txt)" > foo.txt

Dikkat: Bu komut, içinde herhangi bir sondaki yeni satırı korumaz foo.txt. Daha fazla bilgi için aşağıdaki yorum bölümüne bakınız.

Burada alt kabuk $(...), akım yönlendirme operatörü öncesinde değerlendirilir >, böylece bilgilerin korunması sağlanır.


@KamilMaciorowski: Aslında var tmp=$(cmd; printf q);  printf '%s' "${tmp%q}". Ancak bu cevapla ilgili başka bir sorunu kaçırdınız: “komut değiştirme” anlamına geldiğinde “alt kabuk” yazıyor. Evet, komut ikameleri genellikle alt kabuklardır, ancak tam tersi değildir ve genel olarak alt kabuklar bu soruna yardımcı olmaz.
Scott

@KamilMaciorowski Tüm bunları kaçırdığım için kendimi çok kötü hissediyorum. Tüm bunları işaret ettiğiniz için teşekkürler. (4). Noktanız için: backquotes hile yapar mı yani takip eden yeni satır (lar) ı korur mu?
Louis-Jacob Lebel

@ Yanıtınız için teşekkür ederiz. "Komut yerine koyma" için "alt kabuğu" değiştirdim. Bu arada, ikisi arasındaki kesin farkın ne olduğunu merak ediyorum.
Louis-Jacob Lebel

Hayır, backquotes (backticks) sondaki yeni satır karakterlerini de kaldırır.
Kamil Maciorowski

Pekala, şimdilik bir uyarı mesajı ekledim. Bir çözüm bulursam kaldırırım.
Louis-Jacob Lebel
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.