Czy przekierowywanie jednego pliku do drugiego jest UUOC (bezużyteczne użycie cat)?

36

Jeśli chcę file2dopasować zawartość do zawartości file1, oczywiście mógłbym po prostu uruchomić cp file1 file2.

Jednakże, jeśli chcę zachować wszystko o file2 wyjątkiem tej Contents-właściciela, uprawnień, rozszerzonych atrybutów, ACL, twardych linków, etc., etc., to ja nie chce uruchomić cp. * W tym przypadku po prostu chcę plop zawartość file1w file2.

Wygląda na to, że:

< file1 > file2

Ale to nie działa. file2jest obcięty do zera i nie jest napisany do. Jednak,

cat < file1 > file2

wykonuje pracę.

Zaskoczyło mnie, że pierwsza wersja nie działa.

Czy druga wersja to UUOC? Czy można to zrobić bez wywoływania polecenia, używając jedynie przekierowań?

Uwaga: Zdaję sobie sprawę, że UUOC jest bardziej pedantycznym punktem niż prawdziwy anty-wzór.

* Jak odkrył tniles09 , w rzeczywistości cp będzie działać w tym przypadku.

Dzika karta
źródło
3
To, < file1 > file2czy chcesz, co chcesz, zależy od powłoki.
Michael Homer,
13
Cóż, to jest bezużyteczne Zastosowanie <...
jwodder
2
jaki jest anty-wzór ?
mikeserv
6
@jwodder - to nieprawda. szczególnie, gdy mówisz o kopii. zastanów się, co się stanie, gdy file1nie istnieje lub jest nieczytelny, i otwórz go < przed > otwarciem wyjścia, a następnie zastanów się, co się stanie, gdy pozwolisz catspróbować go otworzyć.
mikeserv
3
@JonathanLeffler W Zsh wywołuje się puste polecenie z przekierowaniami cat(domyślnie), zasadniczo uruchamiając drugie polecenie. Zobacz odpowiedź Stéphane'a Chazelasa poniżej, aby uzyskać więcej informacji na ten temat niż mieści się w komentarzu.
Michael Homer,

Odpowiedzi:

58

cat < file1 > file2nie jest UUOC. Klasycznie <i >wykonuj przekierowania, które odpowiadają duplikacjom deskryptorów plików na poziomie systemu. Duplikacje deskryptorów plików same w sobie nic nie robią (no cóż, >przekierowania otwierają się O_TRUNC, aby być dokładnym, przekierowania wyjściowe powodują obcięcie pliku wyjściowego). Nie daj się < >zwieść symbolom. Przekierowania nie przenoszą danych - przypisują deskryptory plików do innych deskryptorów plików.

W takim przypadku otwierasz file1i przypisujesz ten deskryptor pliku do deskryptora pliku 0( <file1== 0<file1) file2oraz przypisujesz ten deskryptor pliku do deskryptora pliku 1( >file2== 1>file2).

Teraz, gdy masz dwa deskryptory plików, potrzebujesz procesu przeszukiwania danych między nimi - i po to catjest.

PSkocik
źródło
11
Może to tylko ja, ale moją ulubioną częścią tej odpowiedzi jest użycie słowa „łopata”. :) Bardzo jasne, dziękuję.
Wildcard,
1
@Wildcard Wolałbym „pompować” niż „łopatę”, ale wciąż dobre słowo. +1
Mehrdad,
dlaczego łopata to dobre słowo?
bubakazouba,
1
Jedna przerzuca łopatę, jedna łopata zapełniana na raz, z jednego stosu na drugi, ponieważ dane są kopiowane bufor po buforze. To dobra analogia.
bsd,
1
W pierwszym zdaniu mówisz, że deskryptory plików są duplikowane. Czy są powielane lub ponownie przypisywane (jak wydaje się wskazywać twój drugi akapit i zachowanie funkcji)?
Greg Bell,
17

Nie jest tak, ponieważ jak zauważyli inni, dane zachowanie zależy od powłoki. Jak zauważyliście (OP), jest to trochę pedantyczne , a może nawet humorystyczne? , rodzaj tematu.

Jednak w systemach GNU, początkowy przesłanka ma innego rozwiązania dostępne: cp --no-preserve=all file1 file2. Wypróbuj to, myślę, że zaspokoi opisaną sytuację (np. Modyfikując zawartość, file2ale nie modyfikując jej atrybutów).

Przykład :

$ 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!

UPDATE Faktycznie, Właśnie zauważyłem, że mój system na cpsam zdaje się zachować atrybuty chyba -aalbo -psą określone. Używam powłoki bash i coreutils GNU. Myślę, że codziennie uczysz się czegoś nowego ...


Wyniki testu (według Wildcard), w tym twardy link i różne uprawnienia:

$ 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
$ 
tniles
źródło
Miły. Przeprowadziłem własny test, w tym twardy link i różne uprawnienia i wygląda na to, że masz rację.
Wildcard
Dodano moje wyniki testu; mam nadzieję, że nie masz nic przeciwko. :) Nie testowałem list ACL ani rozszerzonych atrybutów, ale biorąc pod uwagę, że numer i-węzła jest zachowany, jestem w 99% pewien, że one również będą.
Wildcard
Fajnie ... nie przejmuj się wcale. :-)
tniles
13

W zshpowłoce, w której < file1 > file2działa, powłoka jest wywoływana cat.

W przypadku wiersza poleceń, który składa się tylko z przekierowań, bez polecenia ani przypisań, zshwywołuje $NULLCMD( catdomyślnie), chyba że jedynym przekierowaniem jest to, <w którym zamiast tego wywoływane jest $READNULLCMD( pagerdomyślnie). (to zshznaczy, chyba że jest w shlub cshemulacji, w którym to przypadku zachowuje się jak emulowane powłoki).

Więc:

< file1 > file2

jest w rzeczywistości taki sam jak

cat < file1 > file2

i

< file1

jest taki sam jak

pager < file1
Stéphane Chazelas
źródło
Dla przypomnienia, ta składnia nie działa dla ksh93
fpmurphy,
8
< from > to

nie działa, ponieważ nie ma tam żadnego polecenia; bez procesu. Powłoka otwiera / tworzy pliki i porządkuje przekierowania (co oznacza, że ​​deskryptory plików odnoszące się do tych plików są umieszczane jako 0 i 1: standardowe wejście i standardowe wyjście). Ale nie ma nic do zrobienia, aby wykonać pętlę do odczytu ze standardowego wejścia i zapisu na standardowe wyjście.

zshsprawia, że ​​działa to poprzez zastąpienie polecenia konfigurowanego przez użytkownika w tym przypadku „polecenia zerowego”. Polecenie nie jest widoczne w wierszu polecenia, ale nadal tam jest. Proces jest dla niego tworzony i działa w ten sam sposób. NULLCMDjest catdomyślnie, więc < from > towłaściwie oznacza cat < from > to in zsh, chyba że NULLCMDjest ustawiony na coś innego; jest to polecenie „ukrytego kota”.

„Bezużyteczne użycie cat” występuje, gdy catjest używane jako pośrednik do odczytu z pliku i przekazania danych do innego procesu, którego deskryptor pliku można po prostu podłączyć do oryginalnego pliku.

Jeśli catmożna usunąć z sytuacji, tak że pozostałe polecenia mogą nadal wykonywać to samo zadanie, jest to bezużyteczne. Jeśli nie można go usunąć, to nie jest bezużyteczny.

# 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)

To, catco można wymienić, to nie to samo. Na przykład zamiast cat > filemożemy użyć vi filedo utworzenia pliku. Nie liczy się to jako usunięcie cat, podczas gdy wszystko, co pozostało, do wykonania tego samego zadania.

Jeśli catjest to jedyne polecenie w potoku, to oczywiście nie można go usunąć; żadne przegrupowanie tego, co pozostanie, nie wykona równoważnej pracy.

Niektórzy skrypty powłoki używają, catponieważ uważają, że pozwala im to przenieść operand wejściowy bliżej lewej strony wiersza poleceń. Przekierowania mogą być jednak w dowolnym miejscu wiersza poleceń:

# If you're so inclined:
# move source archive operand to the left without cat:
$ < archive.tar tar xf - > listing
Kaz
źródło
btw, nie musisz używać f -do tar. tar xf -jest po prostu tar x.
dnt
@mikeserv Gdzie to jest powiedziane, że catjest zaangażowany w tworzenie pliku? Odpowiedź wyraźnie mówi, że powłoka to robi. Z jakim problemem > filemasz na myśli? Często używam go osobno do obcięcia istniejącego pliku do zera lub zapewnienia, że ​​taki istnieje. To pytanie dotyczy tego, dlaczego < from > totak nie działa cat < from > to, a UUoC, a nie „proszę podać powody, dla których catnie jest dobrym substytutem cp”.
Kaz
1
@dnt, tarto archiwizator taśm . Wiele tarimplementacji nadal domyślnie działa z pierwszym urządzeniem taśmowym.
Stéphane Chazelas,
1

< file1 > file2 Wydaje się być zależny od powłoki, działa na Zsh, a nie na bash.

edycja: usunięte fałszywe oświadczenie

tastytea
źródło
cp -azachowuje atrybuty pliku 1 i zastępuje atrybuty pliku 2. Przeciwnie do pożądanego zachowania. Nie mogę nawet powiedzieć, patrząc na stronę podręcznika, co się stanie z twardymi linkami, ale myślę, że można bezpiecznie powiedzieć, że twarde linki pliku 2 nie zostaną zachowane.
Wildcard
Masz rację, nie przeczytałem pytania wystarczająco ostrożnie.
tastytea
1

Oprócz wszystkich dobrych odpowiedzi, można uniknąć UUOC przez symulowaniecat :

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

Te polecenia nie kopiują metadanych pliku, jak zwykły cp.

Jens
źródło
To prawda, ale warto wspomnieć, że nie mają one żadnych zalet, a jedynie wady (wydajność, niezawodność) cat. Tutaj potrzebujesz polecenia, aby przesunąć dane między dwoma deskryptorami plików i catjest jednym z najlepszych do tego. Zobacz także, pvktóry mógłby być użyty splice()w Linuksie dla systemu Fifos (choć nie działa tak fadvise(POSIX_FADV_SEQUENTIAL)jak GNU cat).
Stéphane Chazelas,
ddPolecenia dla plików binarnych wydaje się dobre ... czy będzie catdziałać tak samo dobrze dla plików binarnych?
Wildcard,
@Wildcard catdziała również dla plików binarnych (Unix generalnie nie rozróżnia; jednak niektóre narzędzia działają konkretnie linia po linii, takie jak awk, grep, wc, ... POSIX określa również minimalną największą długość linii, więc teoretycznie narzędzie zorientowane na linie może odmówić radzenia sobie z nadmiernie dużymi liniami.)
Jens,
2
@ StéphaneChazelas Ta odpowiedź również była przeznaczona do wymówienia języka. Wygląda na to, że pomimo sezonu niektóre osoby są uczulone na zabawę (nie są skierowane na ciebie; cenię twoją wiedzę na temat powłok i działanie standardów Opengroup).
Jens
sed '' < file1 > file2;-)
Cyfrowa trauma
0

Jeśli to działa, nie naprawiaj tego.

użyłbym

cat < file1 > file2

i nie przejmuj się komputerem semantyki.

krazykyngekorny
źródło