Объединить несколько файлов, но включить имя файла в качестве заголовка раздела

227

Я хотел бы объединить несколько текстовых файлов в один большой файл в терминале. Я знаю, что могу сделать это, используя команду cat. Тем не менее, я хотел бы, чтобы имя файла каждого файла предшествовало "дампу данных" для этого файла. Кто-нибудь знает, как это сделать?

что у меня есть:

file1.txt = bluemoongoodbeer

file2.txt = awesomepossum

file3.txt = hownowbrowncow

cat file1.txt file2.txt file3.txt

желаемый результат:

file1

bluemoongoodbeer

file2

awesomepossum

file3

hownowbrowncow
  • 0
    Я на самом деле использую uuencode & uudecode, чтобы сделать что-то подобное, мне не нужен промежуточный файл для чтения, нужен только результат и перенаправить их в другую команду
  • 0
    unix.stackexchange.com/questions/12342/...
Теги:
terminal
header
concatenation
cat

15 ответов

279

Ищет то же самое, и нашел это, чтобы предложить:

tail -vn +1 file1.txt file2.txt file3.txt

Вывод:

==> file1.txt <==
<contents of file1.txt>

==> file2.txt <==
<contents of file2.txt>

==> file3.txt <==
<contents of file3.txt>

Если есть только один файл, заголовок не будет напечатан. Поэтому используйте -v, чтобы всегда печатать заголовок.

  • 2
    Это работает и с хвостом GNU (частью GNU Coreutils).
  • 0
    Я хочу объединить большое количество файлов. Если я использую это ( tail +1 *.txt ), я получаю сообщение об ошибке Too many open files . Я исправил это с помощью: OLD_ULIMIT=`ulimit -n`;ulimit -n 1024;tail +1 *.txt;ulimit -n $OLD_ULIMIT; , Где 1024 было достаточно большим для меня.
Показать ещё 5 комментариев
123

Я использовал grep для чего-то подобного:

grep "" *.txt

Он не дает вам "заголовок", но префикс каждой строки с именем файла.

  • 1
    Спасибо, это сработало лучше для меня!
  • 7
    Выходные данные прерываются, если *.txt расширяется только до одного файла. В связи с этим я бы посоветовал grep '' /dev/null *.txt
Показать ещё 6 комментариев
68

Это также должно сделать трюк:

find . -type f -print -exec cat {} \;

Средства:

find    = linux `find` command finds filenames, see `man find` for more info
.       = in current directory
-type f = only files, not directories
-print  = show found file
-exec   = additionally execute another linux command
cat     = linux `cat` command, see `man cat`, displays file contents
{}      = placeholder for the currently found filename
\;      = tell `find` command that it ends now here

Далее вы можете комбинировать поиск через логические операторы, такие как -and или -or. find -ls тоже приятно.

  • 1
    Не могли бы вы объяснить подробнее, что делает эта команда? Это именно то, что мне нужно
  • 0
    и на самом деле это работает хорошо, даже без инструкции -print
Показать ещё 5 комментариев
19

Это должно сделать трюк:

for filename in file1.txt file2.txt file3.txt; do
    echo "$filename"
    cat "$filename"
done > output.txt

или сделать это для всех текстовых файлов рекурсивно:

find . -type f -name '*.txt' -print | while read filename; do
    echo "$filename"
    cat "$filename"
done > output.txt
  • 1
    не работал Я только что написал действительно ужасный код awk: для меня в $ listoffiles do awk '{print FILENAME, $ 0, $ 1, $ 2, $ 3, $ 4, $ 5, $ 6, $ 7, $ 8, $ 9, $ 10, $ 11}' $ i >> concat.txt сделано
  • 2
    ... хотите уточнить? Это примерно так же просто, как это делает bash-код.
Показать ещё 9 комментариев
14
find . -type f -print0 | xargs -0 -I % sh -c 'echo %; cat %'

Это будет печатать полное имя файла (включая путь), а затем содержимое файла. Он также очень гибкий, поскольку вы можете использовать -ex "expr" для команды find и запускать столько команд, сколько хотите в файлах.

  • 1
    Это также довольно просто в сочетании с grep . Для использования с bash : find . -type f -print | grep PATTERN | xargs -n 1 -I {} -i bash -c 'echo ==== {} ====; cat {}; echo'
12

У меня была серия файлов, которые закончились в файле stats.txt, который я хотел объединить с именами файлов.

Я сделал следующее, и когда имеется более одного файла, команда "больше" включает имя файла в качестве заголовка.

more *stats.txt > stats.txt

или для общего случая

more FILES_TO_CONCAT > OUTPUT_FILE
  • 4
    more <FILES> | cat
4

Вот как я обычно обрабатываю форматирование следующим образом:

for i in *; do echo "$i"; echo ; cat "$i"; echo ; done ;

Я вообще передаю кошку в grep для конкретной информации.

  • 2
    Будьте осторожны здесь. for i in * не буду включать подкаталоги.
3

вы можете использовать эту простую команду вместо использования цикла for,

ls -ltr | awk '{print $9}' | xargs head
2

Если вам нравятся цвета, попробуйте следующее:

for i in *; do echo; echo $'\e[33;1m'$i$'\e[0m'; cat $i; done | less -R

или

tail -n +1 * | grep -e $ -e '==.*'

или: (с установленным пакетом "multitail" )

multitail *
  • 1
    Ради цветов выделяя имя файла: find . -type f -name "*.txt" | xargs -I {} bash -c "echo $'\e[33;1m'{}$'\e[0m';cat {}"
2

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

Попробуйте это

head -n99999999 * или head -n99999999 file1.txt file2.txt file3.txt

Надеюсь, что поможет

  • 4
    более чистый синтаксис: head -n -0 file.txt file2.txt file3.txt . Работает для head в GNU coreutils
1

Этот метод будет печатать имя файла, а затем содержимое файла:

tail -f file1.txt file2.txt

Вывод:

==> file1.txt <==
contents of file1.txt ...
contents of file1.txt ...

==> file2.txt <==
contents of file2.txt ...
contents of file2.txt ...
  • 2
    Параметр -f полезен, если вы хотите отслеживать файл, в который производится запись, но на самом деле не в рамках того, о чем спрашивал ОП.
0

Мне нравится эта опция

for x in $(ls ./*.php); do echo $x; cat $x | grep -i 'menuItem'; done

Результат выглядит следующим образом:

./debug-things.php
./Facebook.Pixel.Code.php
./footer.trusted.seller.items.php
./GoogleAnalytics.php
./JivositeCode.php
./Live-Messenger.php
./mPopex.php
./NOTIFICATIONS-box.php
./reviewPopUp_Frame.php
            $('#top-nav-scroller-pos-<?=$active**MenuItem**;?>').addClass('active');
            gotTo**MenuItem**();
./Reviews-Frames-PopUps.php
./social.media.login.btns.php
./social-side-bar.php
./staticWalletsAlerst.php
./tmp-fix.php
./top-nav-scroller.php
$active**MenuItem** = '0';
        $active**MenuItem** = '1';
        $active**MenuItem** = '2';
        $active**MenuItem** = '3';
./Waiting-Overlay.php
./Yandex.Metrika.php
0
  • AIX 7.1 ksh

... приглядываясь к тем, кто уже упомянул head, для некоторых из нас:

$ r head
head file*.txt
==> file1.txt <==
xxx
111

==> file2.txt <==
yyy
222
nyuk nyuk nyuk

==> file3.txt <==
zzz
$

Мне нужно прочитать первую строку; как отмечено, если вы хотите более 10 строк, вам придется добавлять опции (head -9999 и т.д.).

Извините за публикацию производного комментария; У меня нет достаточного количества уличного кредитора для комментария/добавления к комментирующему комментарию.

0

Если вы хотите, чтобы результат был в том же формате, что и ваш желаемый результат, вы можете попробовать:

for file in `ls file{1..3}.txt`; \
do echo $file | cut -d '.' -f 1; \ 
cat $file  ; done;

Результат:

file1
bluemoongoodbeer
file2
awesomepossum
file3
hownowbrowncow

Вы можете поместить echo -e до и после разреза, чтобы у вас было расстояние между строками:

$ for file in `ls file{1..3}.txt`; do echo $file | cut -d '.' -f 1; echo -e; cat $file; echo -e  ; done;

Результат:

file1

bluemoongoodbeer

file2

awesomepossum

file3

hownowbrowncow
  • 0
    Объяснение: for цикла проходит через Перечислите ls команда привела. $ ls file{1..3}.txt Результат: file1.txt file2.txt file3.txt каждой итерации будет echo в $file строку , то это водопроводной в cut команды , где я . в качестве разделителя полей, который разбивает fileX.txt на две части и печатает field1 (field2 - это txt). Остальное должно быть ясно
0
find . -type f -exec cat {} \; -print

Ещё вопросы

Сообщество Overcoder
Наверх
Меню