Как уже отмечали другие, использование cat или awk вместо цикла read-echo - гораздо лучший способ сделать это - избежать проблемы обрезки пробелов (и нескольких других, с которыми вы не сталкивались), работает быстрее, и, по крайней мере, с кошкой, это просто более чистый код. Тем не менее, я хотел бы попытаться заставить цикл чтения-эхо работать правильно.
Во-первых, проблема с пропуском пробелов: команда чтения автоматически обрезает начальные и конечные пробелы; это можно исправить, изменив определение пробела, установив пустую переменную IFS. Кроме того, read предполагает, что обратная косая черта в конце строки означает, что следующая строка является продолжением и должна быть соединена вместе с этой; чтобы исправить это, используйте флаг -r (raw). Третья проблема здесь заключается в том, что многие реализации echo интерпретируют escape-последовательности в строке (например, они могут превращать \ n в фактическую новую строку); чтобы исправить это, используйте printf. Наконец, как общее правило гигиены сценариев, вы не должны использовать cat, когда вам это не нужно; вместо этого используйте перенаправление ввода. С этими изменениями внутренний цикл выглядит так:
while IFS='' read -r line; do
printf "%s\n" "$line">>$OUTPUT
done <$f
... есть также несколько других проблем с окружающим сценарием: строка, которая пытается определить FILES как список доступных .textile файлов, имеет кавычки, означающие, что она никогда не будет расширена в фактический список файлов , Лучший способ сделать это - использовать массив:
FILES=(../best-practices/*.textile)
...
for f in "${FILES[@]}"
(и все вхождения $ f должны быть в двойных кавычках на тот случай, если в именах файлов есть пробелы или другие забавные символы - действительно следует делать это и с $ OUTPUT, хотя, поскольку это определено в сценарии, на самом деле безопасно оставить.)
Наконец, есть echo "">$OUTPUT
в верхней части зацикленных файлов, которые будут стирать выходной файл каждый раз до конца (т.е. в конце он содержит только последний файл .textile); это должно быть перемещено до цикла. Я не уверен, было ли здесь намерение поставить одну пустую строку в начале файла или три пустые строки между файлами (и одну в начале и две в конце), поэтому я не уверен, что именно соответствующая замена есть. Во всяком случае, вот что я могу сделать после устранения всех этих проблем:
#!/bin/sh
OUTPUT="../best_practices.textile"
FILES=(../best-practices/*.textile)
: >"$OUTPUT"
for f in "${FILES[@]}"
do
echo "Processing $f file..."
echo >>"$OUTPUT"
while IFS='' read -r line; do
printf "%s\n" "$line">>"$OUTPUT"
done <"$f"
echo >>"$OUTPUT"
echo >>"$OUTPUT"
done