Как добавить новую строку в конец файла?

Меню Search->Replace (или Ctrl+h). Заполните находят и заменяют поля, расширяются Replace All, нажать In Session

Пошаговый:

Выберите "Замену" из меню Search.

Select "Replace" from Search menu.

Расширьтесь, "заменяют все"

Expand "Replace All"

Нажмите "In Session"

Click "In Session"

195
18.02.2016, 19:06
13 ответов

Чтобы рекурсивно дезинфицировать проект, который я использую этот OneLiner:

git ls-files -z | while IFS= read -rd '' f; do tail -c1 < "$f" | read -r _ || echo >> "$f"; done

Объяснение:

  • GIT LS-файлы -Z перечислены файлы в репозитории. Это требует дополнительного шаблона в качестве дополнительного параметра, который может быть полезен в некоторых случаях, если вы хотите ограничить операцию определенным файлам / каталогам. В качестве альтернативы, вы можете использовать Найти -Print0 ... или аналогичные программы для списка пострадавших файлов - просто убедитесь, что он излучает Nul -DELIMID.

  • В то время как ifs = read -ird '' f; Делайте ... Готово , итерации через записи, безопасно обрабатывающие имена файлов, которые включают пробел и / или новые линии.

  • Хвост -C1 <«$ F» Читает последний символ из файла.

  • READ -R _ выходит с ненулевым состоянием выхода, если отсутствует трейлинг Newline.

  • || ECHO >> «$ F» добавляет новую строку в файл, если состояние выхода предыдущей команды было ненулевым.

45
27.01.2020, 19:28

Вы - более обеспеченное исправление редактора пользователя, кто продержался, отредактировал файл. Если Вы - последний человек, который отредактировал файл - какой редактор Вы использование, я предполагаю textmate..?

4
27.01.2020, 19:28
  • 1
    Vim является рассматриваемым редактором. Но в целом, Вы правы, я должен не только зафиксировать symptons ;) –  k0pernikus 17.02.2012, 15:46
  • 2
    для энергии, необходимо стараться изо всех сил и сделать танец binary-file-on-save, чтобы заставить энергию не добавлять, что новая строка в конце файла - просто не делает того танца. ИЛИ, для простого исправления существующих файлов открывают их в энергии и сохранили файл, и энергия 'зафиксирует' недостающую новую строку для Вас (может быть легко задан сценарием для нескольких файлов), –  AD7six 17.02.2012, 15:50
  • 3
    Мой emacs не добавляйте новую строку в конце файла. –  enzotib 20.02.2012, 19:45
  • 4
    Спасибо за комментарий @AD7six я продолжаю получать фантомные отчеты от diffs, когда я фиксирую вещи, о том, как исходный файл не имеет новой строки в конце. Неважно, как я редактирую файл с энергией, я не могу заставить ее не помещать новую строку там. Таким образом, это - просто энергия, делающая его. –  Steven Lu 21.06.2013, 22:39
  • 5
    @enzotib: Я имею (setq require-final-newline 'ask) в моем .emacs –  Keith Thompson 19.02.2016, 20:59

Другое использование решения ed. Это решение только влияет на последнюю строку и только если \n отсутствует:

ed -s file <<< w

Это по существу работает, открывая файл на редактирование через сценарий, сценарий является синглом w команда, которые записывают файл обратно к диску. Это основано на этом предложении, найденном в ed(1) страница справочника:

LIMITATIONS
       (...)

       If  a  text (non-binary) file is not terminated by a newline character,
       then ed appends one on reading/writing it.  In the  case  of  a  binary
       file, ed does not append a newline on reading/writing.
16
27.01.2020, 19:28
  • 1
    Это не добавляет новую строку для меня. –  Olhovsky 12.04.2013, 04:46
  • 2
    Работы для меня; это даже печатает "Новую строку, добавленную" (ed-1.10-1 на Дуге Linux). огромное спасибо –  Stefan Majewsky 10.03.2015, 12:00

Посмотрите:

$ echo -n foo > foo 
$ cat foo
foo$
$ echo "" >> foo
$ cat foo
foo

так echo "" >> noeol-file должен добиться цели. (Или Вы означали просить идентификацию этих файлов и фиксацию их?)

редактирование, удаленное "" от echo "" >> foo (см. комментарий @yuyichao), edit2 добавил "" снова (но см. комментарий @Keith Thompson's),

41
27.01.2020, 19:28
  • 1
    "" не необходимо (по крайней мере, для удара) и tail -1 | wc -l может использоваться для обнаружения файла без новой строки в конце –  yuyichao 17.02.2012, 16:42
  • 2
    @yuyichao: "" не необходимо для удара, но я видел echo реализации, которые ничего не печатают при вызове без аргументов (хотя ни один из тех я могу найти теперь, делают это). echo "" >> noeol-file вероятно, немного более устойчиво. printf "\n" >> noeol-file еще больше. –  Keith Thompson 17.02.2012, 19:17
  • 3
    @KeithThompson, csh echo одно известное ничего для вывода при отсутствии передачи никакой аргумент. Но затем если мы собираемся поддерживать неподобные границе оболочки, мы должны сделать его echo '' вместо echo "" как echo "" был бы ouput ""<newline> с rc или es например. –  Stéphane Chazelas 19.02.2016, 13:49
  • 4
    @StéphaneChazelas: И tcsh, в отличие от этого, csh, печатает новую строку при вызове без аргументов - независимо от установки $echo_style. –  Keith Thompson 19.02.2016, 20:55

Вот:

sed -i -e '$a\' file

И альтернативно для OS X sed:

sed -i '' -e '$a\' file

Это добавляет \n в конце файла, только если это уже не заканчивается новой строкой. Таким образом, при выполнении его дважды это не добавит другую новую строку:

$ cd "$(mktemp -d)"
$ printf foo > test.txt
$ sed -e '$a\' test.txt > test-with-eol.txt
$ diff test*
1c1
< foo
\ No newline at end of file
---
> foo
$ echo $?
1
$ sed -e '$a\' test-with-eol.txt > test-still-with-one-eol.txt
$ diff test-with-eol.txt test-still-with-one-eol.txt
$ echo $?
0
210
27.01.2020, 19:28
  • 1
    @jwd: От man sed: $ Match the last line. Но возможно это работает только случайно. Ваше решение также работает. –  l0b0 20.02.2012, 13:54
  • 2
    Ваше решение также более изящно, и я протестировал и фиксировал его, но как оно может работать? Если $ соответствует последней строке, почему она не добавляет другую новую строку к строке, которая уже содержит новую строку? –  l0b0 20.02.2012, 14:09
  • 3
    Существует два различных значения $. В regex, такой как с формой /<regex>/, это имеет обычный "конец соответствия строки" значение. Иначе, используемый в качестве адреса, sed дает ему специальную "последнюю строку в файле" значение. Код работает, потому что sed по умолчанию добавляет новую строку к своему выводу, если это уже не там. В коде "$a \" просто говорится, "соответствуют последней строке файла, и ничего не добавляют к нему". Но неявно, sed добавляет новую строку к каждой строке, которую это обрабатывает (такие как это $ строка), если это уже не там. –  jwd 22.02.2012, 21:07
  • 4
    Относительно страницы справочника: кавычка, к которой Вы обращаетесь, находится под разделом "Addresses". Вставление его /regex/ дает ему другое значение. Страницы справочника FreeBSD немного более информативны, я думаю: freebsd.org/cgi/man.cgi?query=sed –  jwd 22.02.2012, 21:15
  • 5
    Если файл уже заканчивается в новой строке, это не изменяет его, но он действительно переписывает его и обновляет его метку времени. Это может или не может иметь значения. –  Keith Thompson 19.02.2016, 21:01

Добавьте новую строку независимо:

echo >> filename

Вот способ проверить, существует ли новая строка в конце прежде, чем добавить один, при помощи Python:

f=filename; python -c "import sys; sys.exit(open(\"$f\").read().endswith('\n'))" && echo >> $f
15
27.01.2020, 19:28
  • 1
    я не использовал бы версию Python ни в каком виде цикла из-за медленного времени запуска Python. Конечно, Вы могли сделать цикл в Python, если бы Вы хотели. –  Kevin Cox 09.11.2013, 16:03
  • 2
    Время запуска для Python составляет 0,03 секунды здесь. Вы действительно полагаете, что это проблематично? –  Alexander 10.11.2013, 13:48
  • 3
    Время Запуска действительно имеет значение, называете ли Вы Python в цикле, именно поэтому я сказал, рассматривают выполнение цикла в Python. Затем Вы только несете расходы запуска однажды. Для меня половина стоимости запуск является больше чем половиной времени целого snipit, я полагал бы что существенные издержки. (Снова, не важный, только делая небольшое количество файлов), –  Kevin Cox 11.11.2013, 18:35
  • 4
    echo "" кажется более устойчивым, чем echo -n '\n'. Или Вы могли использовать printf '\n' –  Keith Thompson 19.02.2016, 20:58

Хотя это непосредственно не отвечает на вопрос, вот связанный сценарий, который я записал для обнаружения файлов, которые не заканчиваются в новой строке. Это очень быстро.

find . -type f | # sort |        # sort file names if you like
/usr/bin/perl -lne '
   open FH, "<", $_ or do { print " error: $_"; next };
   $pos = sysseek FH, 0, 2;                     # seek to EOF
   if (!defined $pos)     { print " error: $_"; next }
   if ($pos == 0)         { print " empty: $_"; next }
   $pos = sysseek FH, -1, 1;                    # seek to last char
   if (!defined $pos)     { print " error: $_"; next }
   $cnt = sysread FH, $c, 1;
   if (!$cnt)             { print " error: $_"; next }
   if ($c eq "\n")        { print "   EOL: $_"; next }
   else                   { print "no EOL: $_"; next }
'

Сценарий жемчуга читает список (дополнительно отсортированный) имена файлов от stdin, и для каждого файла он читает последний байт, чтобы определить, заканчивается ли файл в новой строке или нет. Это очень быстро, потому что это старается не читать все содержание каждого файла. Это производит одну строку для каждого файла, который это читает, снабженный префиксом "ошибку": если некоторая ошибка происходит, "пустая": если файл пуст (не заканчивается новой строкой!), "EOL": ("конец строки"), если файл заканчивается новой строкой и "никаким EOL": если файл не заканчивается новой строкой.

Примечание: сценарий не обрабатывает имена файлов, которые содержат новые строки. Если Вы находитесь на GNU или системе BSD, Вы могли бы обработать все возможные имена файлов путем добавления-print0 для нахождения,-z к виду, и-0 к жемчугу, как это:

find . -type f -print0 | sort -z |
/usr/bin/perl -ln0e '
   open FH, "<", $_ or do { print " error: $_"; next };
   $pos = sysseek FH, 0, 2;                     # seek to EOF
   if (!defined $pos)     { print " error: $_"; next }
   if ($pos == 0)         { print " empty: $_"; next }
   $pos = sysseek FH, -1, 1;                    # seek to last char
   if (!defined $pos)     { print " error: $_"; next }
   $cnt = sysread FH, $c, 1;
   if (!$cnt)             { print " error: $_"; next }
   if ($c eq "\n")        { print "   EOL: $_"; next }
   else                   { print "no EOL: $_"; next }
'

Конечно, необходимо было бы все еще придумать способ закодировать имена файлов новыми строками в выводе (оставленный как осуществление для читателя).

Вывод мог быть фильтрован при желании для добавления новой строки в те файлы, которые не имеют один, наиболее просто с

 echo >> "$filename"

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

По моему опыту, отсутствие заключительной новой строки заставлено при помощи различных утилит Windows отредактировать файлы. Я никогда не видел, что энергия вызывает недостающую заключительную новую строку при редактировании файла, хотя она сообщит относительно таких файлов.

Наконец, там намного короче (но медленнее) сценарии, которые могут циклично выполниться по их исходным данным имени файла для печати тех файлов, которые не заканчиваются в новой строке, такой как:

/usr/bin/perl -ne 'print "$ARGV\n" if /.\z/' -- FILE1 FILE2 ...
2
27.01.2020, 19:28

Это работает в AIX ksh:

lastchar=`tail -c 1 *filename*`
if [ `echo "$lastchar" | wc -c` -gt "1" ]
then
    echo "/n" >> *filename*
fi

В моем случае, если в файле отсутствует новая строка, команда wc возвращает значение 2 и мы записываем новую строку.

-1
27.01.2020, 19:28

Редакторы vi / vim / ex автоматически добавляют в EOF, если файл еще не имеет его.

Попробуйте либо:

vi -ecwq foo.txt

, что эквивалентно:

ex -cwq foo.txt

Тестирование:

$ printf foo > foo.txt && wc foo.txt
0 1 3 foo.txt
$ ex -scwq foo.txt && wc foo.txt
1 1 4 foo.txt

Чтобы исправить несколько файлов, проверьте: Как исправить «Нет новой строки в конце файла» для большого количества файлов? в SO

Почему это так важно? Чтобы наши файлы были совместимы с POSIX .

1
27.01.2020, 19:28

Если вы просто хотите быстро добавить новую строку при обработке какого-либо трубопровода, используйте следующее:

outputting_program | { cat ; echo ; }

она также совместима с POSIX.

Тогда, конечно, вы можете перенаправить его в файл.

3
27.01.2020, 19:28

Чтобы применить принятый ответ ко всем файлам в текущем каталоге (плюс подкаталоги):

$ find . -type f -exec sed -i -e '$a\' {} \;

Это работает в Linux (Ubuntu). В OS X вам, вероятно, придется использовать -i '' (непроверено).

0
27.01.2020, 19:28

При условии, что во входных данных нет нулей:

paste - <>infile >&0

... будет достаточно, чтобы всегда добавлять новую строку только в конец файла infile, если у него ее еще нет. И ему нужно только прочитать входной файл один раз, чтобы все было правильно.

3
27.01.2020, 19:28

Простой, переносимый, POSIX-совместимый способ добавления отсутствующей последней новой строки в текстовый файл:

[ -n "$(tail -c1 file)" ] && echo >> file

Этот подход не требует чтения всего файла; он может просто искать EOF и работать оттуда.

Этот подход также не требует создания временных файлов за вашей спиной (например, sed -i), поэтому жесткие ссылки не затрагиваются.

echo добавляет новую строку в файл только тогда, когда результатом подстановки команды является непустая строка. Обратите внимание, что это может произойти, только если файл не пуст и последний байт не является новой строкой.

Если последний байт файла является новой строкой, tail возвращает ее, затем подстановка команды удаляет ее; в результате получается пустая строка. Тест -n не проходит, и echo не запускается.

Если файл пуст, результатом подстановки команд также будет пустая строка, и снова echo не запускается. Это желательно, поскольку пустой файл не является недействительным текстовым файлом и не эквивалентен непустому текстовому файлу с пустой строкой.

12
27.01.2020, 19:28

Теги

Похожие вопросы