Определите, не имеет ли файл EOL в конце из командной строки

Вы можете попробовать это:

sed 's/~.*~//' file > file_new

Вывод будет:

478|14395189_p0.jpg
479|44836628_p0.jpg
480|Miku_Collab_2_by_Luciaraio.jpg
3
18.09.2019, 23:33
3 ответа

tail -c 1 выводит последний символ (, точнее, последний байт )своего ввода.

Подстановка команд удаляет завершающий символ новой строки, поэтому $(tail -c 1 <…)является пустым , если последний символ файла является новой строкой. Он также пуст, если последний символ является нулевым байтом (в большинстве оболочек ), но текстовые файлы не имеют нулевых байтов.

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

if [ ! -s "$filename" ]; then
  echo "$filename is empty"
elif [ -z "$(tail -c 1 <"$filename")" ]; then
  echo "$filename ends with a newline or with a null byte"
else
  echo "$filename does not end with a newline nor with a null byte"
fi
8
27.01.2020, 21:15

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

printf '\n' > newline_only
tail -c 1 your_file | cmp -s newline_only -

Я использовал cmp -s, чтобы сделать cmpпрактически бесшумным. Статус выхода 0указывает на то, что в самом конце your_fileесть символ новой строки.

Если your_fileпусто, статус выхода будет 1. В этом случае вы можете сделать исключение и получить 0. Если это так, добавьте новую строку к тому, что cmpполучает через стандартный ввод:

( printf '\n'; tail -c 1 your_file ) | cmp -s newline_only -
# or
cat newline_only your_file | tail -c 1 | cmp -s newline_only -
# or better
<your_file cat newline_only - | tail -c 1 | cmp -s newline_only -

Последний вариант несколько лучше, потому что он вернет не -нулевой статус выхода, если your_fileне существует, не может быть прочитан и т. д. На вашем месте я бы этого хотел. Хотя, если your_fileна самом деле является каталогом, тогда cat, tailи cmpбудут запущены, и вы можете получить 0и жалобу от cat; а может и нет, см.:Когда каталоги перестали читаться как файлы?). Поэтому вам может понадобиться некоторая дополнительная логика или опция (, например. set -o pipefailв Баше ).

Примечания:

  • В некоторых оболочках вы можете использовать подстановку процессов, чтобы избежать создания файла newline_only. Это будет как:

    # e.g. in Bash
    < your_file cat <(printf '\n') - | tail -c 1 | cmp -s <(printf '\n') -
    
  • tailчтение из канала не может искать. catнужно прочитать весь your_file, только тогда tailсможет выполнить свою работу. tail -c 1 your_fileили <your_file tail -c 1могут оказаться достаточно умными, чтобы искать внутри your_file. Это должно быть незначительным, если вы тестируете один или несколько небольших файлов.

  • Это другое решение , вероятно, будет работать лучше :оно не создает файлы; он не передается в tail; он не появляется cmp;он использует [, встроенный во многие оболочки.
0
27.01.2020, 21:15

На самом деле это не имеет ничего общего с vim. В значительной степени вы хотите

tail -c 1 file

, чтобы получить последний символ файла.

1
27.01.2020, 21:15

Теги

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