Как найти файлы, в конце которых нет пустой строки?

Кредит на https: //unix.stackexchange.com / a / 12772/61349 для получения инструкций по диагностике.

Убедитесь, что ваш ssh-клиент запрашивает перенаправление X11 с флагом -v

ssh example.com -X -v

И найдите конкретное сообщение:

 debug1: Запрос перенаправления X11 с подменой аутентификации. 
 

Еще одним явным признаком проблемы является отсутствие заданной переменной среды DISPLAY . Если он пуст / не установлен, что-то не так. По крайней мере, согласно той же публикации, указанной выше , эти переменные устанавливаются для вас автоматически.


Я использовал SSH Control Master для моих ssh-соединений следующим образом:

Host 
    ControlMaster auto
    ControlPath ~/.ssh/control/%r@%h:%p
    ControlPersist 10m

Мое предыдущее ssh-соединение не запрашивало X11Firwarding, поэтому будущие параметры вызова ssh не использовались. Так что для меня

ssh -X просто полностью игнорировался

Если вы не видите «Запрос перенаправления X11», но видите, что мультиплексор повторно использует сеансы;

 debug1: auto-mux: попытка существующего мастера 
debug1: mux_client_request_session: идентификатор основного сеанса: 10 
 

Затем вам нужно выйти из текущего ControlMaster для этого подключения и повторно подключиться с флагом -X / -Y .

Чтобы остановить ваш ControlMaster

ssh -O check

 Master запущен (pid = 2758) 
 

(Это приведет к выходу из всех активных соединений, использующих ControlMaster)

ssh -O exit

 Запрос на выход отправлен. 
 

9
17.10.2016, 04:13
4 ответа

Чтобы уточнить, символ LF (он же \ n или новая строка) является разделителем строки , а не разделителем строк. Строка не заканчивается, если она не заканчивается символом новой строки. Файл, содержащий только a \ nb , не является допустимым текстовым файлом, поскольку он содержит символы после последней строки. То же самое для файла, содержащего только и . Файл, содержащий a \ n , содержит одну непустую строку.

Таким образом, файл, который заканчивается хотя бы одной пустой строкой, заканчивается двумя символами новой строки или содержит один символ новой строки.

Если:

 tail -c 2 file | od -An -vtc

Выводит \ n или \ n \ n , то файл содержит по крайней мере одну завершающую пустую строку. Если он ничего не выводит, то это пустой файл, если он выводит <ничего, кроме- \ 0> \ n , то он заканчивается непустой строкой. Что-нибудь еще, это не текстовый файл.

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

find . -type f -size +0 -exec gawk '
  ENDFILE{if ($0 == "") print FILENAME}' {} +

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

В идеале вам понадобится оболочка, которая может сама читать конец файла.

С zsh :

zmodload zsh/system
for f (**/*(D.L+0)) {
  {
    sysseek -w end -2
    sysread
    [[ $REPLY = $'\n' || $REPLY = $'\n\n' ]] && print -r -- $f
  } < $f
}
15
27.01.2020, 20:04

С помощью gnu sed и оболочки типа zsh (или bash с shopt -s globstar):

sed -ns '${/./F}' ./**/*.styl

здесь проверяется, не пуста ли последняя строка каждого файла, если да, то выводится имя файла.
Если вы хотите получить обратное (вывести имена файлов, если последняя строка пуста), просто замените /. / на /^$/

6
27.01.2020, 20:04

Правильно завершенный текстовый файл с пустой последней строкой заканчивается двумя \ n .

Затем мы ожидаем, что tail -c2 должен быть равен $ '\ n \ n' .

К сожалению, расширения команд удаляют завершающие новые строки. Нам потребуется небольшая настройка.

f=filename
nl='
'
t=$(tail -c2 $f; printf x)  # capture the last two characters.
r="${nl}${nl}$"                 # regex for: "ends in two newlines".
[[ ${t%x} =~ $r ]] &&  echo "file $f ends in an empty line"

Мы могли бы даже немного расширить, чтобы проверить, какие файлы не имеют завершающей новой строки:

nl='
'
nl=$'\n'
find . -type f -name '*.styl' | while read f; do
    t=$(tail -c2 $f; printf x); r1="${nl}$"; r2="${nl}${r1}"
    [[ ${t%x} =~ $r1 ]] || echo "file $f is missing a trailing newline"
    [[ ${t%x} =~ $r2 ]] && echo "$f"
done

Обратите внимание, что при необходимости новую строку можно изменить на что-то вроде $ '\ r \ n .
В этом случае также измените tail -c2 на tail -c4 .

2
27.01.2020, 20:04
for file in *; do
    # Check if the file is readable to avoid clutter
    if cat "./$file" 2&>1 /dev/null; then
        # Compare the last character with a single newline character.
        if [ -n "$(tail -c 1 -- "./$file")" ]; then
            echo "$file"
        fi
        # Also report empty files.
        if [ $(wc -c  < "./$file") -eq 0 ]; then
            echo "$file"
        fi
    fi
done
{{ 1}}
0
27.01.2020, 20:04

Теги

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