Команда Linux об'єднати файл у себе n разів


31

Я взяв із Project Gutenberg звичайну книгу текстових файлів (близько 0,5 МБ), яку хочу приєднати до себе n, щоб генерувати великий текстовий файл, на який я можу орієнтувати деякі алгоритми. Чи є команда linux, яку я можу використовувати для досягнення цього? catзвучить ідеально, але, здається, не дуже добре грати з приєднанням файлу до себе, плюс безпосередньо не стосується nчасової частини питання.


2
використовувати якусь петлю, і додавати? тому повторіть foo.txt >> bar.txt і оберніть це в щось, що буде виконувати команду, що багато разів?
Подорожник Geek

Відповіді:


35

Дві частини до цього, для мене - перше - використовувати cat для виведення текстового файлу на стандартний вихід, а за допомогою додавання додати його до іншого файлу - наприклад, foo.txt >> bar.txt додасть foo.txt до bar.txt

потім запустіть її n разів за допомогою

for i in {1..n};do cat foo.txt >> bar.txt; done

замінивши n в цій команді своїм номером

повинен працювати, де n - ваш номер

Якщо ви використовуєте csh, є команда "повторити".

повторення пов'язаних частин відповіді скопійовано звідси , і я перевірив її на системі ubuntu 11.04 на оболонці bash за замовчуванням.


3
Забавний факт: це насправді працює без заміни 'n', і в цьому випадку він виконає тіло один раз для кожного символу між ASCII '1' і ASCII 'n' (так 62 рази). Але {1..12}правильно запустити тіло 12 разів.
Арнут Енгелен

1
Ви можете просто перенаправити весь конвеєр, а не додавати в кожній ітерації:for i in {1..n};do cat foo.txt; done > bar.txt
Toby Speight,

2

Мені нудно, ось ось ще кілька методів, як об'єднати файл у себе, в основному, headяк милицю. Вибачте, якщо я переосмислив себе, я просто люблю говорити: P


Якщо припустити, Nце кількість самозв'язків, які ви хочете зробити, і ваш файл названий file.

Змінні:

linecount=$(<file wc -l)

total_repeats=$(echo "2^$N - 1" | bc) # obtained through the power of MATH

total_lines=$((linecount*(total_repeats+1)))

tmp=$(mktemp --suffix .concat.self)

З огляду на копію fileвиклику file2, total_repeatsскільки разів fileпотрібно було б додати, щоб file2вона була такою ж, як якщо б вона fileбула приєднана до себе Nразів.

Сказаний MATH тут, більш-менш: MATH (суть)

Це речі з інформатики першого семестру, але минуло певний час, коли я зробив довідку про індукцію, тому не можу перебороти це ... (також цей клас рекурсії досить добре відомий, щоб 2^Loopsтак було і там).


POSIX

Я використовую декілька не-позитивних речей, але вони не є істотними. Для моїх цілей:

 yes() { while true; do echo "$1"; done; }

О, я лише цим користувався. Ну добре, розділ вже тут ...


Методи


head з відстеженням лінійних ліній.

ln=$linecount
for i in $(seq 1 $N); do
    <file head -n $ln >> file;
    ln=$((ln*2))
done

Ні тимчасового файлу, ні кішки, ні навіть занадто багато математики, вся радість.


teeз MATH

<file tee -a file | head -n $total_lines > $tmp
cat $tmp > file

Тут teeчитається з, fileале постійно додається до нього, тож він продовжує читати файл повторенням, поки не headзупинить його. І ми знаємо, коли це зупинити через МАТ . Додаток додається за борт, тому я використовував тимчасовий файл. Ви можете також обрізати зайві лінії file.


eval, володар темряви!

eval "cat $(yes file | head -n $((total_repeats+1)) | tr '\n' ' ')" > $tmp
cat $tmp > file

Це просто розширюється cat file file file ...і зрівняється з ним. Ви також можете зробити це без $tmpфайлу:

eval "cat $(yes file | head -n $total_repeats | tr '\n' ' ')" |
  head -n $((total_lines-linecount)) >> file

Другий head"хитрощі" cat, поставивши середнього чоловіка між ним та операцією запису. Ви можете також обдурити catіншого cat, але це непослідовно. Спробуйте це:

test_double_cat() {
    local Expected=0
    local Got=0
    local R=0
    local file="$(mktemp --suffix .double.cat)"
    for i in $(seq 1 100); do

        printf "" > $file
        echo "1" >> $file
        echo "2" >> $file
        echo "3" >> $file

        Expected=$((3*$(<file wc -l)))

        cat $file $file | cat >> $file

        Got=$(<file wc -l)

        [ "$Expected" = "$Got" ] && R="$((R+1))"
    done
    echo "Got it right $R/100"
    rm $file
}

sed:

<file tr '\n' '\0' |
    sed -e "s/.*/$(yes '\0' | head -n $total_repeats | tr -d '\n')/g" |
        tr '\0' '\n' >> file

Змушує sedчитати весь файл як рядок, захоплює його, а потім вставляє його $total_repeatsкілька разів.

Це, звичайно, не вдасться, якщо у вашому файлі є будь-які нульові символи. Виберіть того, якого ви знаєте, там немає.

find_missing_char() {
  local file="${1:-/dev/stdin}"

  firstbyte="$(<$file fold -w1 | od -An -tuC | sort -un | head -n 1)"
  if [ ! "$firstbyte" = "0" ]; then
    echo "\0"
  else
    printf "\\$(printf '%03o\t' $((firstbyte-1)) )"
  fi
}

Це все зараз хлопці, я сподіваюся, що ця довільна відповідь нікого не турбувала. Я перевіряв їх усіх багато разів, але я лише дворічний користувач оболонки, тому майте на увазі, я думаю. Тепер спати ...

rm $tmp


2

Ви, звичайно, можете використовувати catдля цього:

$ cat /tmp/f
foo
$ cat /tmp/foo /tmp/f
foo
foo

Для того, щоб отримати $nкопії, ви можете використовувати yesВодопровідний в head -n $n:

$ yes /tmp/f | head -n 10
/tmp/f
/tmp/f
/tmp/f
/tmp/f
/tmp/f
/tmp/f
/tmp/f
/tmp/f
/tmp/f
/tmp/f

Поєднання, що разом дає

yes /tmp/f | head -n $n | xargs cat >/tmp/output
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.