Как добавить один файл к другому в Linux из оболочки?

418

У меня есть два файла: file1и file2. Как мне добавить содержимое file2к file1так, чтобы содержимое file1сохранялось в процессе?

Асир
источник

Ответы:

611

Используйте встроенное перенаправление bash (tldp) :

cat file2 >> file1
Дэвид
источник
2
Как вы это делаете, файл назначения не принадлежит вам, и вам нужно использовать sudo?
Биджай Рунгта
1
@BijayRungta: Похоже, вы ответили на свой вопрос. Вы бы предварительно ПЭНД sudoв catкоманде (и ввести учетные данные , если это будет предложено).
Дэвид
вам нужно ... chmod 777 / etc / default / docker, чтобы дать себе права на запись в этот файл - обязательно восстановите старые разрешения для файла, как только это будет сделано
danday74
1
@Sigur: Если нет способа направить вывод сразу в два файла, это будет связано с двумя вызовами команды.
Дэвид
2
@ Сигур или взгляните на teeпрограмму cat 1 | tee -a 2 3. Вы можете поместить столько файлов, сколько захотите после --append(или -aдля краткости) переключения.
Стефан ван ден Аккер
291

cat file2 >> file1

>>Оператор добавляет вывод в указанный файл или создает указанный файл , если он не существует.

cat file1 file2 > file3

Это объединяет два или более файлов в один. Вы можете иметь столько исходных файлов, сколько вам нужно. Например,

cat *.txt >> newfile.txt

Обновление 20130902
В комментариях eumiro предлагается «не пытайтесь cat file1 file2 > file1». Причина, по которой это может не привести к ожидаемому результату, состоит в том, что файл, получающий перенаправление, готовится до выполнения команды слева от >. В этом случае сначала file1обрезается до нулевой длины и открывается для вывода, затем catкоманда пытается объединить теперь файл нулевой длины плюс содержимое file2в file1. Результатом является то, что оригинальное содержимое file1утеряно и на его месте находится копия, file2которая, вероятно, не соответствует ожидаемой.

Обновление 20160919
В комментариях tpartee предлагает ссылки на информацию / источники поддержки. Для авторитетной ссылки я направляю доброго читателя на страницу man sh адресу linuxcommand.org, где говорится:

Перед выполнением команды ее ввод и вывод могут быть перенаправлены с использованием специальных обозначений, интерпретируемых оболочкой.

Хотя это говорит читателю, что им нужно знать, его легко пропустить, если вы не ищете его и анализируете утверждение слово за словом. Самое важное здесь слово «до». Перенаправление завершено (или не выполнено) до выполнения команды.

В примере с cat file1 file2 > file1 оболочка сначала выполняет перенаправление, чтобы дескрипторы ввода-вывода были в месте, в котором команда будет выполнена до ее выполнения.

Более дружелюбную версию, в которой приоритет перенаправления подробно описан, можно найти на веб-сайте Яна Аллена в форме учебного курса по Linux. Его страница « Примечания о перенаправлении ввода / вывода» может многое сказать по этой теме, включая наблюдение, что перенаправление работает даже без команды. Передав это в оболочку:

$ >out

... создает пустой файл с именем out. Оболочка сначала устанавливает перенаправление ввода / вывода, затем ищет команду, не находит ни одной и завершает операцию.

T.Rob
источник
17
@asir - не пытайтесь cat file1 file2 > file1- это не сработает, как вы, вероятно, ожидаете.
Eumiro
5
На самом деле это именно то, что ему нужно. Он говорит «без перезаписи текущего файла1». Первые три автора полностью проигнорировали эту часть вопроса и предложили команду, >>которая будет изменять файл file1. T.Rob проделал гораздо лучшую работу, объясняя свой ответ, чем просто мчался, чтобы представить что-то, что было на самом деле неверно. Основываясь на тексте вопроса, я считаю, что cat file1 file2 > file3это подходящая команда, которую искал @asir.
dm78
Спасибо за добрые слова, Дэвид! На что @eumiro указывает выше, но не вдавается в подробности, так это то, что >сначала выполняется операция справа от . Таким образом, выполнение cat file1 file2 > file1сначала заклинило бы, а file1затем попыталось скопировать файл нулевой длины на себя. Это имеет смысл, когда вы думаете о порядке, в котором операции могут и должны происходить, но достаточно тонко, чтобы застать многих врасплох. Так что, если ничего другого, eumiro и вы предложили дальнейшее улучшение ответа. Спасибо за это!
T.Rob
Также не пытайтесь использовать cat file1 >> file1, это приведет к рекурсивной перезаписи файла, я по ошибке делаю это, и в течение нескольких секунд в файл было вставлено 50 миллионов строк из нескольких предыдущих строк.
Хендра
Кроме того, просто для того, чтобы сделать его более кратким, если «новый файл» уже существует, >> добавляется к файлу и > заменяет файл.
Риного
43

Примечание : если вам нужно использовать sudo , сделайте это:

sudo bash -c 'cat file2 >> file1'

Обычный метод простого добавления sudoк команде не удастся, поскольку повышение привилегий не переносится в перенаправление вывода.

jdunk
источник
6
Еще одна распространенная идиома для этогоcat file2 | sudo tee -a file1 > /dev/null
ianw
28

Попробуйте эту команду:

cat file2 >> file1
eumiro
источник
13

Просто для справки, использование ddrescue обеспечивает прерываемый способ решения задачи, если, например, у вас есть большие файлы и вам нужно сделать паузу, а затем продолжить на более позднем этапе:

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

Это logfileважный бит. Вы можете прервать процесс Ctrl-Cи возобновить его, указав ту же самую команду снова, и ddrescue прочитает logfileи возобновит с того места, где он остановился. -o AФлаг говорит ddrescue , чтобы начать с байта А в выходном файле ( file1). Так wc --bytes file1 | awk '{ print $1 }'что просто извлекает размер file1в байтах (вы можете просто вставить в вывод из, lsесли хотите).

Как отмечено в комментариях ngks , недостатком является то, что ddrescue, вероятно, не будет установлен по умолчанию, поэтому вам придется установить его вручную. Другая сложность заключается в том, что в ваших репозиториях могут быть две версии ddrescue: дополнительную информацию смотрите в этом вопросе аскубунту . Нужная версия - GNU ddrescue, а в системах на основе Debian - пакет с именем gddrescue:

sudo apt install gddrescue

Для других дистрибутивов проверьте вашу систему управления пакетами для версии ddrescue GNU .

Зоравар
источник
1
Для новых пользователей: ddrescue - это инструмент GNU, но он может не существовать в вашей Linux, Mac или другой unix-подобной системе. По-видимому, ddrescue не требуется POSIX или любым другим стандартом.
2

Другое решение:

cat file1 | tee -a file2

tee имеет то преимущество, что вы можете добавлять столько файлов, сколько хотите, например:

cat file1 | tee -a file2 file3 file3

добавит содержимое file1к file2, file3и file4.

Со страницы руководства:

-a, --append
       append to the given FILEs, do not overwrite
Стефан ван ден Аккер
источник
0

catможет быть простым решением, но оно становится очень медленным, когда мы объединяем большие файлы, find -print- это спасение вас, хотя вам придется использовать 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
Амей Джадие
источник
Экономия времени, которую вы сообщаете для своей комбинированной команды find / cat, заключается в том, что вы синхронизируете только команду find, которая печатает имена файлов. Попробуйте синхронизировать всю команду следующим образом: результаты time (find . -maxdepth 1 -type f -name 'bigFile*' -print0 | xargs -0 cat -- > outFile1)должны быть такими же, как у вашей команды cat only.
JoshMc
0

Вы также можете сделать это без cat, хотя, честно говоря cat, более читабельно:

>> file1 < file2

>>Присоединяет STDIN к file1и <отвалов file2на STDIN .

Алок Сингх
источник
@ user202729 Вы правы, это не работает в Bash. Это работает в Zsh.
Алок Сингх