Cat ile '>' arasındaki fark bir dosyayı sıfırlamak için


23

Bu iki komut, dosyaları sıfıra nasıl soktukları konusunda farklı mıdır? İkincisi eskisini yapmak için daha kısa bir yol mu? Sahne arkasında neler oluyor?

Her ikisi de

$ cat /dev/null > file.txt

$ > file.txt 

Yol ver

-rw-r--r--  1 user  wheel  0 May 18 10:33 file.txt

Yanıtlar:


28

cat /dev/null > file.txtBir olan kedinin yararsız kullanımı .

Temel olarak cat /dev/nullbasitçe cathiçbir şeyin çıkmamasıyla sonuçlanır . Evet işe yarıyor, ancak birçok kişi tarafından kaşlarını çattı, çünkü gerekli olmayan bir dış sürecin başlatılmasıyla sonuçlandı.
Bu yaygın olan şeylerden biri, çünkü yaygın.

Sadece > file.txtçoğu kabuk üzerinde çalışacak, ancak tamamen taşınabilir değil. Tamamen taşınabilir istiyorsanız, aşağıdakiler iyi alternatiflerdir:

true > file.txt
: > file.txt

Hem :ve trueçıkış hiçbir veri ve (oysa kabuk yerleşiklere vardır cat, bu yüzden, daha hafif ve daha 'uygun' olan bir dış araçtır).

 

Güncelleştirme:

Tylerl'in yorumunda belirtildiği gibi, >| file.txtsözdizimi de var .

Çoğu kabuk, varolan bir dosyayı aracılığıyla kesmelerini önleyen bir ayara sahiptir >. Bunun >|yerine kullanmalısın . Bu, gerçekten eklemek istediğinizde insan hatasını önlemek içindir >>. Davranışı ile ile açabilirsiniz set -C.

Bu nedenle, bir dosyayı kısaltmanın en basit, en uygun ve taşınabilir yönteminin olacağını düşünüyorum:

:>| file.txt

2
İki nokta komutu POSIX'de tanımlanmıştır . Komut satırı argümanlarını genişletmek için mevcut olan boş bir işlemdir.
kojiro

3
LOL, "kedi istismarı"
KM.

2
@kojiro :ayrıca POSIX tarafından yerleşik olması için zorunlu kılınır ve aslında "özel" yerleşiktrue olarak kabul edildiğinden farklıdır .
jw013

2
Noclobber'ı unutma . >| filedaha açık bir kesiktir.
tylerl

1
Hiçbir trueyerleşik olması gerekmez ve bunun geleneksel değildi edilir. :Bourne ailesinin bütün kabukları üzerine inşa edilmiştir. :POSIX başına özel bir yerleşiktir (bu nedenle : > fileörneğin filePOSIX kabuklarına yazmaya açık değilse kabuktan çıkacaktır ) ve truedeğildir. POSIX , bazı sistemlerde olduğundan :daha verimli olabileceğinden bile bahseder true.
Stéphane Chazelas

23

Taşınabilirlik açısından:

                      Bourne POSIX  zsh    csh/tcsh  rc/es  fish
> file                Y      Y      N(1)   N(1)      N      N
: > file              N/Y(2) Y(3)   Y      Y(4)      N(5)   N(5)
true > file           Y(5)   Y      Y      Y(5)      Y(5)   Y(5)
cat /dev/null > file  Y(5)   Y      Y(5)   Y(5)      Y(5)   Y(5)
eval > file           Y(3,8) Y(3)   Y      Y(6)      Y      Y
cp /dev/null file (7) Y(5)   Y      Y(5)   Y(5)      Y(5)   Y(5)
printf '' > file      Y(5)   Y      Y      Y(5)      Y(5)   Y

Notlar:

  1. içinde shveya kshöykünme dışında cat, komutsuz yönlendirmeler için, zsh'da NULLCMD ve READNULLCMD değişkenleriyle ayarlanabilen varsayılan bir komut kabul edilir (yalnızca stdin yeniden yönlendirmesi için bir çağrı cihazı ). Bu benzer özellikten ilham aldı(t)csh
  2. :UnixV7'de, :bir yorum lideri ile bir boş komut arasında yarı yolda yorumlandığı için yönlendirmeler başlangıçta gerçekleştirilmedi . Daha sonra onlar yeniden yönlendirme başarısız olursa, kabuktan çıkan bütün yapıtaşlar için gibiydiler.
  3. :ve evalyönlendirme başarısız olursa, kabuktan çıkan özel yerleşikler ( bashyalnızca POSIX modunda yapar).
  4. İlginçtir ki, içinde (t)cshboş bir etiket tanımlamaktadır (for goto), bu yüzden goto ''orada dallanırdı. Yeniden yönlendirme başarısız olursa, kabuktan çıkar.
  5. Sürece / Karşılık gelen komut mevcut olup olmadığını $PATH( :genellikle değildir; true, cat, cpve printfgenellikle (POSIX) bunları gerektirir).
  6. Yeniden yönlendirme başarısız olursa, kabuktan çıkar.
  7. Eğer filebununla birlikte bir var olmayan bir dosyaya bir sembolik bağdır, bazı cpGNU en gibi uygulamalar oluşturmak için reddedecektir.
  8. Bourne kabuğunun ilk sürümleri, yerleşik yapıların yönlendirilmesini desteklemiyordu.

Okunabilirlik açısından:

(bu bölüm son derece özneldir)

  • > file. Bu >bir bilgi istemi veya yorum gibi görünüyor. Ayrıca bunu okurken soracağım soru (ve çoğu kabukları da aynı şekilde şikayet edecek) tam olarak ne yönlendiriyorsunuz? .
  • : > file. :no-op komutu olarak bilinir. Böylece boş bir dosya oluştururken hemen okunur. Bununla birlikte, yine burada, bu :kolayca kaçırılabilir ve / veya hızlı bir şekilde görülebilir.
  • true > file: yönlendirme veya dosya içeriği ile ne ilgisi var? Burada ne kastedilmektedir? Bunu okuduğumda aklıma gelen ilk şey.
  • cat /dev/null > file. Concatenate /dev/nulliçine file? catgenellikle dosyanın içeriğini dökümü komutu olarak görülüyor, o halen mantıklı olabilir: içeriğini dökümü içine boş dosyadafile bir dolambaçlı bir yol gibi biraz söylemek, cp /dev/null fileama yine de anlaşılabilir.
  • cp /dev/null file. Kopya içeriği boş dosyaya için file. Mantıklı gelse cpde, varsayılan olarak nasıl yapılması gerektiğini bilmeyen filebir kişi nullde bir aygıt yapmaya çalıştığınızı düşünebilir .
  • eval > fileveya eval '' > file. Hiçbir şey çalıştırmaz ve çıktısını a'ya yönlendirir file. Bana mantıklı geldi. Ortak bir deyim olmaması garip.
  • printf '' > file: açıkça bir dosyaya hiçbir şey yazdırmaz . Bana en anlamlı olanı.

Performans açısından

Aradaki fark, bir kabuk yerleşik kullanıp kullanmamamız olacaktır. Değilse, bir işlem çatallanmalıdır, komut yüklenip çalıştırılmalıdır.

evaltüm mermilerde inşa edileceği garantilidir. :bulunduğu her yerde yerleşiktir (Bourne / csh sever). truesadece Bourne benzeri kabuklarda yerleşiktir.

printfyerleşik Bourne benzeri kabukları en modern ve fish.

cpve catgenellikle yerleşik değildir.

Şimdi cp /dev/null filekabuk yönlendirmelerini çağırmaz, şöyle şeyler:

find . -exec cp /dev/null {} \;

şunlardan daha verimli olacak:

find . -exec sh -c '> "$1"' sh {} \;

(Gerektiğinde mutlaka değil:

find . -exec sh -c 'for f do : > "$f"; done' sh {} +

).

Şahsen

Şahsen, : > fileBourne benzeri mermilerde kullanıyorum ve bugünlerde Bourne benzeri mermilerden başka bir şey kullanmıyorum.


Ne hakkında dd of=file count=0?
kojiro

2
@kojiro, dd(En azından Solaris 10'unki gibi) bazı uygulamaları count=0ile dikkate alınmaz. dd if=/dev/null of=filedaha taşınabilir olurdu. Her durumda, bu kabuktan bağımsızdır.
Stéphane Chazelas

Tamam, ama dahil edilmekten daha azını hak etmiyor cp /dev/null file, değil mi?
kojiro

2
@kojiro, cp /dev/null fileortak bir deyimdir. Bunları sınırlandırıyorum, mesele mümkün olan tüm yolları listelemek değildir.
Stéphane Chazelas

5

Şuna bakmak isteyebilirsiniz truncate, ki bu da tam olarak şöyle: bir dosyayı kesmek.

Örneğin:

truncate --size 0 file.txt

Bu muhtemelen kullanmaktan daha yavaştır true > file.txt.

Ancak benim asıl meselem şudur: truncatedosyaları kesmek için kullanılırken,> kullanımı bir dosyayı kesmenin yan etkisine sahiptir.


2
Dediğin 0'dan dışında bir dosya kesmek istediğinizde Truncate, güzel bir kabuk bile olmadan bir bağlam nerede tanımlayabiliriz: garip bir ifadedir truncateama hiçbiri mevcut olacaktır >ne de unistdC kütüphaneleri mevcut olurdu?
kojiro

Pek sayılmaz. Muhtemelen mevcut her senaryo veya programlama dili için daha zarif bir çözüm var.
Fabian

3
truncateGNU çekirdek elemanlarına nispeten yakın zamanda (2008) eklenen bir FreeBSD yardımcı programıdır ( --sizeGNU uzun seçenek stili GNU’ya özgüdür), bu nedenle GNU dışı veya FreeBSD sistemlerinde mevcut değildir ve eski GNU sistemlerinde mevcut değildir, Taşınabilir olduğunu söyleyemem. cp /dev/null fileBir kabuk yönlendirme olmadan çalışır ve daha taşınabilir olurdu.
Stéphane Chazelas

Tamam, bu taşınabilirlik yorumunu kaldıracağım. Son zamanlardaki tanımın farklı görünüyor olsa da.
Fabian

2

Cevap biraz ne file.txtolduğuna ve sürecin ona nasıl yazdığına bağlı!

Yaygın bir kullanım durumundan bahsedeceğim: adında büyüyen bir günlük dosyası var file.txtve döndürmek istiyorsunuz.

Bu nedenle, örneğin file.txtiçine kopyalar file.txt.save, sonra keser file.txt.

Bu senaryoda, eğer dosya açılmazsa another_process(örneğin: another_processo dosyayı çıkaran bir program olabilir, örneğin bir şeyi günlüğe kaydeden bir program olabilir), o zaman 2 teklifiniz eşdeğerdir ve her ikisi de iyi çalışır (ancak 2. olarak tercih edilir). ilk "cat / dev / null> file.txt", Yararsız bir Kullanım Kullanımıdır ve ayrıca açar ve / dev / null okur.

Ancak asıl sorun, eğer other_processhala aktifse ve hala file.txt dosyasına giden açık bir tanıtıcı varsa olacaktır.

Ardından, other processdosyanın nasıl açıldığına bağlı olarak 2 ana durum ortaya çıkar :

  • Eğer other_processnormal şekilde açılır, daha sonra kulp hala ofset 1200 bayt örneğin, dosyada eski konuma işaret olacaktır. Bu nedenle bir sonraki yazma 1200 ofset ile başlayacak ve böylece 1200 bitlik boş karakterlerle birlikte yine 1200 byte'lık bir dosya (+ başka bir işlem yazılmadı) olacak! İstediğini değil , sanırım.

  • Eğer other_processaçılan file.txt"ekleme modunda", o zaman yazar her zaman, işaretçi aktif dosyanın sonuna çalışılacak. Bu nedenle, kesildiğinde, 0 baytına kadar "arayacak" ve kötü yan etki yaşamayacaksınız! İstediğiniz budur (… genellikle!)

Bunun bir dosyayı kısaltırken, other_processo konuma hala yazmakta olanların tümünü "ekle" modunda açtığından emin olmak için ihtiyacınız olduğunu unutmayın. Aksi takdirde other_process, bunları durdurmanız ve yeniden başlatmanız gerekir; bu nedenle eski konum yerine dosyanın başlangıcını işaret etmeye başlarlar.

Kaynaklar: /programming//a/16720582/1841533 daha temiz bir açıklama, normal ve ekleme modu günlük arasındaki farkın güzel bir kısa örneğe için /programming//a/984761/1841533


2
Bu cevabın çok az bir kısmı aslında soru ile ilgilidir ya da soruyu cevaplar. A cat /dev/null > fileve a arasındaki fark a > fileolup cat /dev/null, bu dosyada fark yaratmaz.
jw013

@ jw013: Doğru! Ancak sadece çok iyi bilinmediği için "ne istediğinizi / ne istediğinizi değil" bilgisini yeniden sorma fırsatını değerlendirmek istedim ve kütükleri döndürmek isteyen zor birisini vurabilirim (ortak bir durum bir dosyayı kesmek).
Olivier Dulac

1
Her şeyin zamanı ve yeri var. Bilgileriniz başka bir bağlamda yararlı olabilir ancak buraya ait değildir - bunun için daha uygun bir yer bulmalısınız çünkü günlükleri döndürmeye çalışan hiç kimse bu tamamen ilgisiz yönlendirme sorusuna bakmayacaktır. Burada cevabınız bir dijital otun karşılığıdır, tıpkı bir mısır tarlasının ortasındaki başka bir yararlı kabak bitkisinin bir ot olduğu düşünülür.
jw013

1

Bunu beğendim ve sık kullanıyorum çünkü daha temiz görünüyor ve birinin dönüş anahtarına kazayla vurması gibi görünmüyor:

echo -n "" > file.txt

Yerleşik de olmalı mı?


3
Bir dosyayı sıfırlamak için birçok yol vardır. Bence KM. sadece soruda gösterilen iki yöntem arasındaki farkı anlamakla ilgiliydi.
drs

6
Birçok echouygulamalar desteklemez -n(ve çıkış alacaktı -n<SPC><NL>burada. printf '' > file.txt) En az çağdaş / POSIX sistemleri arasında (daha taşınabilir olacaktır.
Stéphane Chazelas
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.