Bir dosyayı diğerine yönlendirmek UUOC (işe yaramaz kedi kullanımı) mı?


36

İçeriğinin file2eşleşmesini yapmak file1istersem, açıkça çalıştırabilirim cp file1 file2.

Ben korumak istiyorsanız Ancak, her şeyi yaklaşık file2 hariç vb içerikleri-sahibi, izinleri, genişletilmiş nitelikler, ACL, sabit bağlantılar, vb, sonra çalıştırmak istemem cp. * Sadece plop istiyorum Bu durumda içeriği file1içine file2.

Aşağıdaki yapacak gibi görünüyor:

< file1 > file2

Fakat işe yaramıyor. file2hiçbir şeye kesilmez ve yazılamaz. Ancak,

cat < file1 > file2

does işi.

İlk versiyonun işe yaramaması beni şaşırttı.

İkinci versiyon bir UUOC mi? Bunu sadece komutları kullanarak komut istemeden yapmanın bir yolu var mı?

Not: UUOC'nin gerçek bir anti-paternden ziyade sinsi bir noktadan geçtiğinin farkındayım.

* As tniles09 keşfetti , cp irade bu durumda aslında çalışmalarında.


3
İster < file1 > file2ne istediğini kabuk bağlıdır yapar.
Michael Homer

13
Eh, o ise bir Yararsız Kullanım <...
jwodder

2
Bir ne anti-desen ?
mikeserv

6
@jwodder - bu doğru değil. özellikle bir kopya hakkında konuşurken. ne olur düşünün file1yok veya başka okunamaz ve size ile açın < önce > çıkış açılır ve sonra izin ne olur düşünün cataçmaya için.
mikeserv

3
@JonathanLeffler zsh içinde yönlendirmeleri çağıran boş bir komut cat(varsayılan olarak), esas olarak ikinci komutu çalıştırır. Bkz Stéphane Chazelas' cevabı daha o yorumunda uyan daha aşağıda.
Michael Homer

Yanıtlar:


58

cat < file1 > file2bir UUOC değil. Klasik olarak <ve >sistem düzeyinde dosya tanımlayıcı kopyalarına karşılık gelen yönlendirmeleri yapar. Dosya tanımlayıcı kopyaları kendi başlarına bir şey yapmaz (peki, >açık olan yönlendirmeler O_TRUNC, böylece doğru olması için, çıkış yönlendirmeleri çıktı dosyasını keser). < >Sembollerin kafanı karıştırmasına izin verme . Yönlendirmeler verileri taşımaz; dosya tanımlayıcılarını diğer dosya tanımlayıcılarına atarlar.

Bu durumda file1bu dosya tanımlayıcısını açıp dosya tanımlayıcısına 0( <file1== 0<file1) file2atar ve bu dosya tanımlayıcısını dosya tanımlayıcısına 1( >file2== 1>file2) atarsınız .

Şimdi iki dosya tanımlayıcınız olduğuna göre, ikisi arasında veri kürekleme işlemine ihtiyacınız var - ve bunun nedeni bu cat.


11
Belki sadece benim, ama bu cevabın en sevdiğim yanı "kürek" kelimesini kullanman. :) Çok açık, teşekkür ederim.
Joker

1
@Wildcard "kürek" yerine "pompa" tercih ederdim ama yine de iyi bir kelime. +1
Mehrdad

kürek neden iyi bir kelime?
bubakazouba

1
Biri, bir defada tam bir kürek olmak üzere, bir kümeden bir kazık kazıkladığından, veriler tamponla tampon olarak kopyalanır. Güzel bir benzetme.
bsd

1
İlk cümlede, dosya tanımlayıcıların kopyalandığını söylüyorsun. Çoğaltılıyorlar mı yoksa yeniden atanıyorlar mı (ikinci paragrafınız ve özelliğin davranışı belirtiyor gibi)?
Greg Bell,

17

Bu, çünkü başkalarının da belirttiği gibi, söz konusu davranış kabuk bağımlı değildir. Siz (OP) işaret ettiğiniz gibi, bu biraz sersemletici , hatta esprili mi? , konuya göre sırala.

Ancak, GNU sistemlerinde, başlangıçtaki öncül başka bir çözüm mevcut bulunmaktadır: cp --no-preserve=all file1 file2. Bunu deneyin, açıkladığınız durumu yerine getireceğini düşünüyorum (örneğin file2, özelliklerini değiştirmese de içeriğini değiştirme).

Örnek :

$ ls -l
    total 8
    -rw-r--r-- 1 tniles sambashare 16 Dec 16 12:21 fezzik
    -rw-r--r-- 1 tniles tniles     14 Dec 16 12:16 fred
$ cat *
    Lookout, world!
    Hello, world!
$ cp --no-preserve=all fred fezzik 
$ ls -l
    total 8
    -rw-r--r-- 1 tniles sambashare 14 Dec 16 12:22 fezzik
    -rw-r--r-- 1 tniles tniles     14 Dec 16 12:16 fred
$ cat *
    Hello, world!
    Hello, world!

GÜNCELLEME Aslında, sistemimin cpkendisinin , belirtilmediği -aveya -pbelirtilmediği sürece özellikleri koruduğunu gördüm . Bash shell ve GNU coreutils kullanıyorum. Sanırım her gün yeni bir şeyler öğreniyorsun.


Sabit bağlantı ve farklı izinler dahil test sonuçları (Wildcard tarafından):

$ ls -li
total 12
913966 -rw-rw-r-- 1 vagrant vagrant 30 Dec 16 20:26 file1
913965 -rwxrw---- 2 pete    vagrant 39 Dec 16 20:35 file2
913965 -rwxrw---- 2 pete    vagrant 39 Dec 16 20:35 hardlinktofile2
$ cat file1
This is the contents of file1
$ cat file2
This is the original contents of file2
$ cp file1 file2
$ ls -li
total 12
913966 -rw-rw-r-- 1 vagrant vagrant 30 Dec 16 20:26 file1
913965 -rwxrw---- 2 pete    vagrant 30 Dec 16 20:37 file2
913965 -rwxrw---- 2 pete    vagrant 30 Dec 16 20:37 hardlinktofile2
$ cat file1
This is the contents of file1
$ cat file2
This is the contents of file1
$ 

Güzel. Sabit bir bağlantı ve farklı izinler dahil kendi testimi yaptım ve doğru gözüküyorsun.
Wildcard,

Test sonuçlarımı ekledi; umarım sakıncası yoktur. :) EKL’leri veya genişletilmiş öznitelikleri test etmedim ancak inode numarasının korunduğunu göz önüne alarak bunların da% 99 eminim.
Wildcard,

Güzel ... hiç umursamıyorum. :-)
tniles

13

İçinde zsh, kabuk < file1 > file2çalıştığı yerde kabuk çağırır cat.

Sadece yönlendirmeler ve bir komut veya atamaları oluşan bir komut hattı için zshçağırır $NULLCMD( catsadece yönlendirme sürece varsayılan) a, <ki bu durumda, bir $READNULLCMD( pageryerine çağrılır varsayılan). (en sürece zshiçindedir shveya cshöykünme bu durumda o öykünür kabukları gibi davranır).

Yani:

< file1 > file2

aslında aynı

cat < file1 > file2

ve

< file1

aynıdır

pager < file1

Kayıt için, bu sözdizimi
ksh93

8
< from > to

çalışmıyor çünkü orada bir komut yok; işlem yok. Kabuk, dosyaları açar / yaratır ve yönlendirmeleri düzenler (bu dosyaları referans alan tanımlayıcıların 0 ve 1 olarak dikildiği anlamına gelir: standart girdi ve standart çıktı). Ancak standart girdiden okumak ve standart çıktıya yazmak için bir döngü yürütecek hiçbir şey yoktur.

zshbu "null komut" durumunda kullanıcı tarafından yapılandırılabilir bir komutun yerini alarak bu işi yapar. Komut, komut satırında görünmüyor, ancak hala orada. Bunun için bir süreç yaratılır ve aynı şekilde çalışır. NULLCMDolduğu cat, bu yüzden varsayılan olarak < from > toaslında anlamı cat < from > to içinde zsholmadıkça, NULLCMDbaşka bir şeye ayarlanır; bu bir "kapalı kedi" komutudur.

Bir catdosyadan okumak ve verileri, dosya tanıtıcısı asıl dosyaya yeni bağlanmış olabilecek başka bir işlemle beslemek için bir aracı olarak kullanıldığında "kedinin yararsız kullanımı" ortaya çıkar .

Eğer catdurumdan çıkarılabilir, kalan komutlar yine aynı görevi gerçekleştirebilir öyle ki, bu işe yaramaz. Çıkarılabilir değilse, o zaman işe yaramaz değil.

# useless, removable:
$ cat archive.tar | tar tf -    #  -->  tar tf archive.tar

# not removable (in POSIX shell):
$ cat > file
abc
[Ctrl-D]

# likewise:
STRING=$(cat file)

A catise Değişebilir aynı şey değildir. Mesela dosyayı oluşturmak için cat > filekullanabiliriz vi file. catAynı işi yapmak için geriye kalanları kullanırken bu , kaldırılması olarak sayılmaz .

Boru hattındaki tek komut buysa cat, elbette kaldırılamaz; Kalan şeyin yeniden düzenlenmesi eşdeğer işi yapmaz.

Bazı kabuk catkomut dosyaları, giriş işleneni komut satırının sol tarafına yaklaştırmalarına izin verdiklerini düşündükleri için kullanırlar . Ancak, yeniden yönlendirme komut satırında herhangi bir yerde olabilir:

# If you're so inclined:
# move source archive operand to the left without cat:
$ < archive.tar tar xf - > listing

BTW, f -katran için kullanmak zorunda değilsiniz . tar xf -sadece tar x.
dnt

@mikeserv Bunun catdosya oluşumuna katıldığı nerede ? Cevap açıkça kabuğun bunu yaptığını söylüyor. Hangi sorunu > filekastediyorsunuz? Genellikle onu varolan bir dosyayı sıfıra kadar kısaltmak ya da var olmasını sağlamak için kullanırım. Bu soru neden < from > toböyle çalışmadığını cat < from > tove UUoC'nin "lütfen bana neden catiyi bir alternatif olmadığına dair nedenler vermeyin" hakkında değildir cp.
Kaz

1
@dnt, tarbir teyp arşiv . Birçok taruygulama hala varsayılan olarak ilk teyp cihazıyla çalışmaktadır.
Stéphane Chazelas

1

< file1 > file2 Kabuğa bağlı görünüyor, çalıştığı zsh'de, bash'de değil.

düzenleme: silinen yanlış ifade


cp -aniteliklerini koruyan Dosya1 ve yazar dosya2'nin özelliklerini. İstenilen davranışın karşısında. Artı ben bile zor bağlantıları ile ne olacağını adam sayfası bakarak söyleyemem, ama söylemek güvenli olduğunu düşünüyorum dosya2 'ın sert bağlantılar olacak değil korunacaktır.
Wildcard,

Haklısın, soruyu yeterince dikkatli okumadım.
tastytea

1

Tüm iyi cevaplara ek olarak, aşağıdakileri simüle ederek UUOC'tan kaçınabilirsiniz cat:

awk 1 file1 > file2   # For line-oriented text, not binaries.
dd if=file1 of=file2  # Works for binary files, too.
# many more geeky ways.

Bu komutlar düz olarak, dosya meta veri kopyalamak yok cpolur.


Doğru, ancak avantajları ve sadece sakıncaları (performans, güvenilirlik) olmadığından bahsetmeye değer cat. Burada iki dosya tanımlayıcısı arasında veri toplamak için bir komuta ihtiyacınız var ve catbunun için en iyilerinden biri. Ayrıca Linux'ta pvhangileri için kullanabileceğini de görün splice()( fadvise(POSIX_FADV_SEQUENTIAL)GNU'nun catyaptığı gibi olmasa da ).
Stéphane Chazelas

ddİkili dosyaları için komut iyi görünüyor ... ya ederim catikili dosyalar için de sadece işe?
Wildcard

@Wildcard catayrıca ikili dosyalar için de çalışır (Unix genellikle ayırt etmez; ancak, bazı araçlar özellikle awk, grep, wc, gibi satır-satır çalışır. Bir çizgi odaklı araç aşırı büyük çizgilerle başa çıkmayı reddedebilir.)
Jens

2
@ StéphaneChazelas Bu cevap aynı zamanda yanak dili olarak da düşünülmüştü. Görünüşe göre, mevsime rağmen, bazı insanlar eğlenceye alerjisi var (size yönelik değil; kabuk uzmanlığınıza ve Opengroup standartlarının çalışmasına değer veriyorum).
Jens

sed '' < file1 > file2;-)
Digital Trauma

0

İşe yararsa, tamir etmeyin.

Kullanmak istiyorum

cat < file1 > file2

ve anlambilimin PC'sini terletmeyin.

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.