Dlaczego to polecenie tworzy niezwykle duży plik?

19

Dzisiaj eksperymentowałem z kilkoma operacjami dołączania i, z ciekawości, uruchomiłem to (gdzie plik1.txt był niepusty i plik2.txt był pusty):

$ cat file1.txt >> file2.txt >> file1.txt

Kiedy zobaczyłem, że zajmuje to trochę czasu, naciśnij Ctrl+, Caby to zakończyć. Do tego czasu plik1.txt miał setki MB.

Zmiana nazw plików nie daje tego samego efektu; tylko wtedy, gdy pliki są w tej kolejności, następuje nieskończone przekierowanie. Co dokładnie się dzieje, co to powoduje?

Matt
źródło

Odpowiedzi:

24

Nie można catw ten sposób użyć wielu standardowych, ostatnie przekierowanie ma pierwszeństwo, więc:

cat file1.txt >> file2.txt >> file1.txt

jest równa:

>> file2.txt ; cat file1.txt >> file1.txt

który oczywiście szybko zapełnia system plików, biorąc pod uwagę fakt, że plik źródłowy będący celem także rośnie w nieskończoność, pod warunkiem, że file1.txtjest wystarczająco duży, aby nie można go było odczytać od razu.

Większość nowoczesnych catimplementacji powinna wykrywać rekurencyjność i przerywać:

Kot Solaris:

cat: input/output files 'file1.txt' identical

Kot GNU:

cat: file1.txt: input file is output file

I tak można ich oszukać za pomocą czegoś takiego:

cat < file1.txt | cat | cat  >> file2.txt >> file1.txt

Miłe, nie tak bezużyteczne korzystanie z kotów ...

jlliagre
źródło
19
To dużo kotów, miau.
slm
2
Sprawiłeś, że kręciło mi się w głowie, ale odpowiedziałeś na moje pytanie!
Matt
7
A kiedy zapytałem o to w Google+ (nie otrzymałem odpowiedzi), automatycznie otagowałem mój wpis #Cat i #Caturday
Matt
3

Nie byłem w stanie odtworzyć tego w powłoce Bash:

# non-empty file1
$ echo 1 > file1.txt

$ cat file1.txt >> file2.txt >> file1.txt 
cat: file1.txt: input file is output file

Zostanie utworzony 1 plik o długości 0, ale następnie pojawia się powyższy komunikat:

$ ls -l
total 4
-rw-rw-r-- 1 saml saml   2 Sep 10 19:35 file1.txt
-rw-rw-r-- 1 saml saml   0 Sep 10 19:35 file2.txt

Na podstawie odpowiedzi @ jlliagre nie jestem pewien, dlaczego otrzymuję 2 pliki. Może to zależeć od catwdrożenia.

EDYCJA 1

@jlliagre zaktualizował swoją odpowiedź, aby pokazać ten kod, który uważa za równoważny:

>> file2.txt ; cat file1.txt >> file1.txt

Więc teraz wiem, dlaczego robię się pusta file2.txt. Ta notacja jest legalna:

>> file2.txt

I utworzy pusty plik.

slm
źródło
Spróbuj ponownie, file1.txtzaczynając od niepustego.
Gilles „SO- przestań być zły”
@Gilles - Właśnie to przeczytałem i zauważyłem, czy powinienem zobaczyć coś innego, nadal pojawia się błąd? A może po prostu mówisz, że b / c przykład w mojej odpowiedzi jest zły? Naprawiłem odpowiedź BTW.
slm
@Gilles - to był twój głos, nie? Czy chodzi tylko o coś konkretnego lub brak wartości odpowiedzi?
slm
1
Nie jestem pewien, dlaczego odrzucono twoją odpowiedź, +1 za przeżycie przed odpowiedzią, coś, czego sam nie zrobiłem ...
jlliagre 10.09.2013
+1; dzięki za eksperymenty! Zaczynam lepiej rozumieć przekierowania i catzachowanie.
Matt