Прочтите руководство по rsync
. Rsync - ваш друг, когда вы хотите сохранить атрибуты.
По сути, чего-то вроде rsync -lHAXogtE
должно быть (более чем) достаточно, если я правильно вас понимаю.
Я бы упростил ваши команды следующим образом:
#!/bin/bash
for file in *.txt; do
cat $file >> Combined.txt
printf '\n\n=========\n\n' >> Combined.txt
done
Если вы собираетесь делать это с тысячами файлов, вы можете не запускать несколько команд для каждого файла. С ГНУawk
:
printf '%s\0'./*.txt | xargs -r0 gawk '
BEGINFILE {if (NR) print "\n==========\n"};1' > combined.out
Не давайте расширение .txt
выходному файлу, если вы собираетесь поместить его в тот же каталог, иначе он будет выбран в качестве входного файла и вызовет бесконечный цикл (, вероятно, ваша проблема в первую очередь ).
Или используйте оболочку, в которой cat
встроен, напримерksh93
:
#! /bin/ksh93
firstpass=true
for file in *.txt; do
"$firstpass" || print '\n===========\n'
firstpass=false
command /opt/ast/bin/cat < "$file"
done > combined.out
Все эти команды в цикле встроены -, поэтому их выполнение не требует создания новых процессов или загрузки внешнего исполняемого файла, что делает производительность приемлемой.
FNR
и NR
вawk
#!/bin/bash
outfile="$( mktemp combined.txt.XXXXXX )"
echo "Output file: ${outfile}"
awk 'FNR==1 && NR>1 { printf("\n%s\n\n","========") } 1' *.txt > "${outfile}"
echo "Finished."
Строка -по -описание строки:
outfile="$( mktemp combined.txt.XXXXXX )"
Используйте mktemp
для создания нового пустого файла с уникальным именем (, например,combined.txt.HDpgMn
). Вы можете использовать больше X
символов для более длинного случайного суффикса. Включите команду в "$(
... )"
, чтобы сохранить имя нового файла в переменной outfile
.
echo "Saving to file: ${outfile}"
Печать имени выходного файла. (Когда сценарий завершится, вы можете переименовать выходной файл, чтобы удалить строку случайных символов, следующую за .txt
.)
awk 'FNR==1 && NR>1 { printf("\n%s\n\n","========") } 1' *.txt > "${outfile}"
Распечатать...
...в начале каждого входного файла, кроме первого входного файла. FNR
подсчитывает количество строк входного файла, сбрасывая значение в начале каждого файла. NR
подсчитывает номера строк и не сбрасывает.
В операторе awk
1
непосредственно перед закрывающей одинарной кавычкой оценивается как TRUE
для каждой строки и выполняет действие по умолчанию для печати этой строки. (Другими словами, awk '1'
работает как cat
.)
echo "Finished."
Сообщить пользователю, когда скрипт завершится. (Не обязательно, так как вы все равно увидите командную строку, но это не помешает.)
Почему бы просто не
printf "\n\n=====\n\n" > XTMP
cat $(printf "%s XTMP " *.txt) > combined.tmp
Поместите разделитель во временный файл и используйте функцию printf
для повторения строки форматирования для каждого найденного аргумента, поэтому команда cat
будет выглядеть как
cat 1.txt XTMP 2.txt XTMP... n.txt XTMP
Вы можете столкнуться с системными ограничениями (, например. LINE _MAX ), хотя...