Jak dołączyć jeden plik do drugiego w Linuksie z powłoki?

418

Mam dwa pliki: file1i file2. Jak dołączyć zawartość file2do file1, aby zawartość file1trwała proces?

asir
źródło

Odpowiedzi:

610

Użyj wbudowanego przekierowania bash (tldp) :

cat file2 >> file1
David
źródło
2
Jak to zrobić, plik docelowy nie jest Twoją własnością i musisz używać sudo?
Bijay Rungta
1
@BijayRungta: Wygląda na to, że odpowiedziałeś na własne pytanie. Wstępnie oczekiwałeś sudona catpolecenie (i wprowadź poświadczenia, jeśli zostaniesz o to poproszony).
David
musisz ... chmod 777 / etc / default / docker, aby dać sobie uprawnienia do zapisu na tym pliku - pamiętaj, aby przywrócić stare uprawnienia do pliku po
zakończeniu
1
@ Sigur: Chyba że istnieje sposób, aby skierować wyjście do dwóch plików jednocześnie, wymagałoby to dwóch wywołań polecenia.
David
2
@Sigur lub spojrzeć w teeprogramie: cat 1 | tee -a 2 3. Możesz umieścić tyle plików, ile chcesz po przełączeniu --append(lub -aw skrócie).
Stefan van den Akker
291

cat file2 >> file1

>>Operator dołącza wyjście do wskazanego pliku lub tworzy plik o nazwie, jeśli nie istnieje.

cat file1 file2 > file3

To łączy dwa lub więcej plików w jeden. Możesz mieć tyle plików źródłowych, ile potrzebujesz. Na przykład,

cat *.txt >> newfile.txt

Aktualizacja 20130902
W komentarzach eumiro sugeruje „nie próbuj cat file1 file2 > file1”. Przyczyną tego może nie być oczekiwany wynik, ponieważ plik odbierający przekierowanie jest przygotowywany przed wykonaniem polecenia po lewej stronie pliku >. W tym przypadku, po pierwsze file1jest obcięty do zerowej długości i otwarty do wyjścia, a następnie catpróby dowodzenia, aby złączyć się teraz plik o zerowej długości plusa zawartość file2do file1. W rezultacie file1utracono oryginalną zawartość, a na jej miejscu znajduje się kopia, file2której prawdopodobnie nie należy się spodziewać.

Aktualizacja 20160919
W komentarzach partner sugeruje połączenie z informacjami / źródłami wsparcia. W celu uzyskania wiarygodnego odniesienia kieruję czytelnika do strony sh man na linuxcommand.org, która stwierdza:

Przed wykonaniem polecenia jego dane wejściowe i wyjściowe mogą zostać przekierowane przy użyciu specjalnej notacji interpretowanej przez powłokę.

Chociaż to mówi czytelnikowi, co powinien wiedzieć, łatwo go przeoczyć, jeśli go nie szukasz i nie analizujesz słowa po słowie. Najważniejszym słowem jest tutaj „przed”. Przekierowanie jest zakończone (lub kończy się niepowodzeniem) przed wykonaniem polecenia.

W tym przypadku cat file1 file2 > file1powłoka najpierw wykonuje przekierowanie, aby uchwyty we / wy znajdowały się w środowisku, w którym polecenie zostanie wykonane przed jego wykonaniem.

Bardziej przyjazną wersję, w której szczegółowo omówiono pierwszeństwo przekierowania, można znaleźć na stronie Iana Allena w formie materiałów szkoleniowych dla systemu Linux. Jego strona Notatki o przekierowaniach we / wy ma wiele do powiedzenia na ten temat, w tym spostrzeżenie, że przekierowanie działa nawet bez polecenia. Przekazywanie tego do powłoki:

$ >out

... tworzy pusty plik o nazwie. Powłoka najpierw konfiguruje przekierowanie We / Wy, a następnie szuka polecenia, nie znajduje go i kończy operację.

T.Rob
źródło
17
@asir - nie próbuj cat file1 file2 > file1- to nie zadziała, jakbyś prawdopodobnie czekał.
eumiro
5
Właściwie tego właśnie potrzebuje. Mówi „bez nadpisywania bieżącego pliku1”. Pierwsze trzy Główni odpowiadający całkowicie zignorował tę część pytania i sugerowane polecenie za pomocą >>którego będzie zmodyfikować plik file1. T.Rob wykonał znacznie lepszą robotę, tłumacząc swoją odpowiedź, niż tylko ścigając się, aby przedstawić coś, co w rzeczywistości było nieprawidłowe. Na podstawie tekstu pytania uważam, że cat file1 file2 > file3jest to właściwe polecenie, którego szukał @asir.
dm78,
Dzięki za miłe słowa, David! To, na co @eumiro wskazuje powyżej, ale nie wchodzi w szczegóły, to to, że operacja po prawej stronie >jest wykonywana jako pierwsza. Więc wykonując cat file1 file2 > file1najpierw sprać file1następnie próbować skopiować plik teraz zero-length na siebie. Ma to sens, gdy myślisz o kolejności, w jakiej operacje mogą i powinny się odbywać, ale jest na tyle subtelne, że zaskakuje wielu ludzi. Więc jeśli nic więcej, eumiro i ty poprosiliście o dalszą poprawę odpowiedzi. Dziękuję za to!
T.Rob
Również nie spróbować cat plik1 >> plik1, to spowoduje, że plik, który ma być rekurencyjnie przepisany, ja przez pomyłkę i po prostu to zrobić w ciągu kilku sekund, 50 mln linii zostały wprowadzone do pliku, z tylko poprzednio kilkudziesięciu linii.
Hendra Uzia
Ponadto, aby uczynić go nieco bardziej zwięzłym, jeśli „nowy plik” już istnieje, >> dołącza się do pliku i > zastępuje plik.
rinogo
43

Uwaga : jeśli potrzebujesz użyć sudo , zrób to:

sudo bash -c 'cat file2 >> file1'

Zwykła metoda zwykłego przygotowania sudodo komendy zakończy się niepowodzeniem, ponieważ eskalacja uprawnień nie zostanie przeniesiona na przekierowanie wyjściowe.

jdunk
źródło
6
Innym powszechnym idiomem tego jestcat file2 | sudo tee -a file1 > /dev/null
ianw
28

Wypróbuj to polecenie:

cat file2 >> file1
eumiro
źródło
13

Dla porównania, użycie ddrescue zapewnia przerywany sposób na wykonanie zadania, jeśli na przykład masz duże pliki i potrzebujesz zatrzymać, a następnie kontynuować w późniejszym momencie:

ddrescue -o $(wc --bytes file1 | awk '{ print $1 }') file2 file1 logfile

To logfilejest ważny kawałek. Możesz przerwać ten proces Ctrl-Ci wznowić go, ponownie określając dokładnie to samo polecenie, a ddrescue będzie czytać logfilei wznawiać od miejsca, w którym zostało przerwane. -o AFlaga mówi ddrescue zacząć od bajtów A w pliku wyjściowym ( file1). Więc wc --bytes file1 | awk '{ print $1 }'po prostu wyodrębnia rozmiar file1w bajtach (możesz po prostu wkleić dane wyjściowe, lsjeśli chcesz).

Jak zauważyli ngks w komentarzach, wadą jest to, że ddrescue prawdopodobnie nie zostanie domyślnie zainstalowany, więc będziesz musiał zainstalować go ręcznie. Inną komplikacją jest to, że istnieją dwie wersje ddrescue, które mogą znajdować się w twoich repozytoriach: zobacz to pytanie askubuntu, aby uzyskać więcej informacji. Wersja, którą chcesz, to GNU ddrescue, a na systemach opartych na Debianie jest to pakiet o nazwie gddrescue:

sudo apt install gddrescue

W przypadku innych dystrybucji sprawdź w systemie zarządzania pakietami wersję ddrescue GNU .

Zorawar
źródło
1
Z korzyścią dla nowych użytkowników: ddrescue jest narzędziem GNU, ale może nie istnieć w systemie Linux, Mac lub innym systemie uniksowym. Wydaje się, że ddrescue nie jest wymagany przez POSIX ani żaden inny standard.
2

Inne rozwiązanie:

cat file1 | tee -a file2

tee ma tę zaletę, że możesz dołączyć dowolną liczbę plików, na przykład:

cat file1 | tee -a file2 file3 file3

doda zawartość file1do file2, file3i file4.

Ze strony podręcznika:

-a, --append
       append to the given FILEs, do not overwrite
Stefan van den Akker
źródło
0

catmoże być łatwym rozwiązaniem, ale staje się bardzo powolne, gdy łączymy duże pliki, find -printma cię uratować, chociaż raz musisz użyć cat.

amey@xps ~/work/python/tmp $ ls -lhtr
total 969M
-rw-r--r-- 1 amey amey 485M May 24 23:54 bigFile2.txt
-rw-r--r-- 1 amey amey 485M May 24 23:55 bigFile1.txt

 amey@xps ~/work/python/tmp $ time cat bigFile1.txt bigFile2.txt >> out.txt

real    0m3.084s
user    0m0.012s
sys     0m2.308s


amey@xps ~/work/python/tmp $ time find . -maxdepth 1 -type f -name 'bigFile*' -print0 | xargs -0 cat -- > outFile1

real    0m2.516s
user    0m0.028s
sys     0m2.204s
Amey Jadiye
źródło
Oszczędności czasu zgłaszane dla komendy find / cat polegają na tym, że mierzysz czas komendy find, która wypisuje nazwy plików. Spróbuj taktować całą komendę w ten sposób: time (find . -maxdepth 1 -type f -name 'bigFile*' -print0 | xargs -0 cat -- > outFile1)powinna ona dać wyniki podobne do komendy cat.
JoshMc
0

Możesz to również zrobić bez cat, choć szczerze mówiąc catjest bardziej czytelny:

>> file1 < file2

>>Dołącza STDIN się file1i <zrzuca file2do standardowego wejścia .

Alok Singh
źródło
1
To nie działa.
user202729
@ user202729 Masz rację, to nie działa w bash. Działa w Zsh.
Alok Singh