Меню Search->Replace
(или Ctrl+h
). Заполните находят и заменяют поля, расширяются Replace All
, нажать In Session
Чтобы рекурсивно дезинфицировать проект, который я использую этот 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»
добавляет новую строку в файл, если состояние выхода предыдущей команды было ненулевым.
Вы - более обеспеченное исправление редактора пользователя, кто продержался, отредактировал файл. Если Вы - последний человек, который отредактировал файл - какой редактор Вы использование, я предполагаю textmate..?
Другое использование решения 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.
Посмотрите:
$ echo -n foo > foo
$ cat foo
foo$
$ echo "" >> foo
$ cat foo
foo
так echo "" >> noeol-file
должен добиться цели. (Или Вы означали просить идентификацию этих файлов и фиксацию их?)
редактирование, удаленное ""
от echo "" >> foo
(см. комментарий @yuyichao), edit2 добавил ""
снова (но см. комментарий @Keith Thompson's),
""
не необходимо (по крайней мере, для удара) и tail -1 | wc -l
может использоваться для обнаружения файла без новой строки в конце
– yuyichao
17.02.2012, 16:42
""
не необходимо для удара, но я видел echo
реализации, которые ничего не печатают при вызове без аргументов (хотя ни один из тех я могу найти теперь, делают это). echo "" >> noeol-file
вероятно, немного более устойчиво. printf "\n" >> noeol-file
еще больше.
– Keith Thompson
17.02.2012, 19:17
csh
echo
одно известное ничего для вывода при отсутствии передачи никакой аргумент. Но затем если мы собираемся поддерживать неподобные границе оболочки, мы должны сделать его echo ''
вместо echo ""
как echo ""
был бы ouput ""<newline>
с rc
или es
например.
– Stéphane Chazelas
19.02.2016, 13:49
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
man sed
: $ Match the last line.
Но возможно это работает только случайно. Ваше решение также работает.
– l0b0
20.02.2012, 13:54
$
соответствует последней строке, почему она не добавляет другую новую строку к строке, которая уже содержит новую строку?
– l0b0
20.02.2012, 14:09
$
. В regex, такой как с формой /<regex>/
, это имеет обычный "конец соответствия строки" значение. Иначе, используемый в качестве адреса, sed дает ему специальную "последнюю строку в файле" значение. Код работает, потому что sed по умолчанию добавляет новую строку к своему выводу, если это уже не там. В коде "$a \" просто говорится, "соответствуют последней строке файла, и ничего не добавляют к нему". Но неявно, sed добавляет новую строку к каждой строке, которую это обрабатывает (такие как это $
строка), если это уже не там.
– jwd
22.02.2012, 21:07
/regex/
дает ему другое значение. Страницы справочника FreeBSD немного более информативны, я думаю: freebsd.org/cgi/man.cgi?query=sed
– jwd
22.02.2012, 21:15
Добавьте новую строку независимо:
echo >> filename
Вот способ проверить, существует ли новая строка в конце прежде, чем добавить один, при помощи Python:
f=filename; python -c "import sys; sys.exit(open(\"$f\").read().endswith('\n'))" && echo >> $f
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 ...
Это работает в AIX ksh:
lastchar=`tail -c 1 *filename*`
if [ `echo "$lastchar" | wc -c` -gt "1" ]
then
echo "/n" >> *filename*
fi
В моем случае, если в файле отсутствует новая строка, команда wc
возвращает значение 2
и мы записываем новую строку.
Редакторы 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 .
Если вы просто хотите быстро добавить новую строку при обработке какого-либо трубопровода, используйте следующее:
outputting_program | { cat ; echo ; }
она также совместима с POSIX.
Тогда, конечно, вы можете перенаправить его в файл.
Чтобы применить принятый ответ ко всем файлам в текущем каталоге (плюс подкаталоги):
$ find . -type f -exec sed -i -e '$a\' {} \;
Это работает в Linux (Ubuntu). В OS X вам, вероятно, придется использовать -i ''
(непроверено).
При условии, что во входных данных нет нулей:
paste - <>infile >&0
... будет достаточно, чтобы всегда добавлять новую строку только в конец файла infile, если у него ее еще нет. И ему нужно только прочитать входной файл один раз, чтобы все было правильно.
Простой, переносимый, POSIX-совместимый способ добавления отсутствующей последней новой строки в текстовый файл:
[ -n "$(tail -c1 file)" ] && echo >> file
Этот подход не требует чтения всего файла; он может просто искать EOF и работать оттуда.
Этот подход также не требует создания временных файлов за вашей спиной (например, sed -i), поэтому жесткие ссылки не затрагиваются.
echo добавляет новую строку в файл только тогда, когда результатом подстановки команды является непустая строка. Обратите внимание, что это может произойти, только если файл не пуст и последний байт не является новой строкой.
Если последний байт файла является новой строкой, tail возвращает ее, затем подстановка команды удаляет ее; в результате получается пустая строка. Тест -n не проходит, и echo не запускается.
Если файл пуст, результатом подстановки команд также будет пустая строка, и снова echo не запускается. Это желательно, поскольку пустой файл не является недействительным текстовым файлом и не эквивалентен непустому текстовому файлу с пустой строкой.
По крайней мере, в версиях GNU просто grep ''
или awk 1
канонизирует свой ввод , добавив последний символ новой строки, если он еще не присутствует. Они копируют файл в процессе, что требует времени, если он большой (но исходный код все равно не должен быть слишком большим для чтения?), И обновляет время модификации, если вы не сделаете что-то вроде
mv file old; grep '' <old >file; touch -r old file
(хотя это может быть нормально для файла, который вы регистрируются, потому что вы его изменили) , и он теряет жесткие ссылки, разрешения не по умолчанию, списки управления доступом и т. д., если вы не проявите еще большую осторожность.
Самый быстрый способ проверить, является ли последний байт файла новой строкой, - это прочитать только этот последний байт. Это можно сделать с помощью tail -c1 file
. Однако упрощенный способ проверить, является ли значение байта новой строкой, в зависимости от оболочки, обычное удаление завершающей новой строки внутри расширения команды не удается (например) в yash, когда последний символ в файле является UTF- 8 значение.
Правильный, POSIX-совместимый, все (разумный) способ оболочки для определения, является ли последний байт файла новой строкой, - это использовать либо xxd, либо hexdump:
tail -c1 file | xxd -u -p
tail -c1 file | hexdump -v -e '/1 "%02X"'
Затем, сравнивая вывод выше с 0A
предоставит надежный тест.
Полезно избегать добавления новой строки в пустой файл.
Файл, который не может предоставить последний символ 0A
, конечно:
f=file
a=$(tail -c1 "$f" | hexdump -v -e '/1 "%02X"')
[ -s "$f" -a "$a" != "0A" ] && echo >> "$f"
Короткий и приятный. Это занимает очень мало времени, так как он просто читает последний байт (переход к EOF). Неважно, большой ли файл. Затем добавьте только один байт, если необходимо.
Временные файлы не нужны и не используются. Никакие жесткие ссылки не затронуты.
Если этот тест запускается дважды, он не добавит еще одну новую строку.
echo $'' >>
добавит пустую строку в конец файла.
echo $'\n\n' >>
добавит 3 пустые строки в конец файла.
Si su archivo termina con Windows finales de línea \r\n
y está en Linux, puede usar este comando sed
. Solo agrega \r\n
a la última línea si aún no está allí:
sed -i -e '$s/\([^\r]\)$/\1\r\n/'
Explicación:
-i replace in place
-e script to run
$ matches last line of a file
s substitute
\([^\r]\)$ search the last character in the line which is not a \r
\1\r\n replace it with itself and add \r\n
Si la última línea ya contiene un \r\n
, la expresión regular de búsqueda no coincidirá, por lo tanto, no pasará nada.
Добавление к ответу Патрика Оссити , если вы просто хотите применить его к определенному каталогу, вы также можете использовать:
find -type f | while read f; do tail -n1 $f | read -r _ || echo >> $f; done
Запустите это внутри каталога, в который вы хотите добавить новые строки.
Самое быстрое решение:
[ -n "$(tail -c1 file)" ] && printf '\n' >>file
Очень быстро.
Для файла среднего размера seq 99999999 >file
это занимает миллисекунды.
Другие решения занимают много времени:
[ -n "$(tail -c1 file)" ] && printf '\n' >>file 0.013 sec
vi -ecwq file 2.544 sec
paste file 1<> file 31.943 sec
ed -s file <<< w 1m 4.422 sec
sed -i -e '$a\' file 3m 20.931 sec
Работает в ash, bash, lksh, mksh, ksh93, attsh и zsh, но не в yash.
Если вам нужно решение, переносимое на yash (и все другие оболочки, перечисленные выше ), это может немного усложниться:
f=file
if [ "$(tail -c1 "$f"; echo x)" != "$(printf '\nx')" ]
then printf '\n' >>"$f"
fi
Вы можете написать fix-non-delimited-line
скрипт типа:
#! /bin/zsh -
zmodload zsh/system || exit
ret=0
for file do
if sysopen -rwu0 -- "$file"; then
if sysseek -w end -1; then
read -r x || print -u0
else
syserror -p "Can't seek in $file before the last byte: "
ret=1
fi
else
ret=1
fi
done
exit $ret
В отличие от некоторых приведенных здесь решений,
Вы можете использовать его, например, как:
that-script *.txt
или:
git ls-files -z | xargs -0 that-script
POSIX, вы могли бы сделать что-то функционально эквивалентное с
export LC_ALL=C
ret=0
for file do
[ -s "$file" ] || continue
{
c=$(tail -c 1 | od -An -vtc)
case $c in
(*'\n'*) ;;
(*[![:space:]]*) printf '\n' >&0 || ret=$?;;
(*) ret=1;; # tail likely failed
esac
} 0<> "$file" || ret=$? # record failure to open
done
Чтобы исправить все файлы в репозитории git, запустите
git ls-files --eol |\
grep -e 'i/lf' |\
grep -v 'attr/-text' |\
sed 's/.*\t//' |\
xargs -d '\n' sed -b -i -e '$a\'
git ls-files --eol
список всех файлов, отслеживаемых git, с атрибутом eol
grep -e 'i/lf'
отфильтровать файлы, зарегистрированные в индексе с помощьюLF
grep -v 'attr/-text'
пропустить файлы, помеченные как binary
или -text
в.gitattributes
sed 's/.*\t//'
отфильтровать все, кроме путей xargs -d '\n' sed -b -i -e '$a\'
добавить новую строку в конец файла -b
обрабатывать файл как двоичный (не трогать концы строк)-i
редактирует файл на месте -e '$a\'
добавить новую строку в конец файла, но только если в конце файла нет новой строки и файл не пустой.