Вы можете попробовать это:
sed 's/~.*~//' file > file_new
Вывод будет:
478|14395189_p0.jpg
479|44836628_p0.jpg
480|Miku_Collab_2_by_Luciaraio.jpg
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
Создайте файл, содержащий только символ новой строки, затем сравните его с последним байтом вашего файла:
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
;он использует [
, встроенный во многие оболочки. На самом деле это не имеет ничего общего с vim
. В значительной степени вы хотите
tail -c 1 file
, чтобы получить последний символ файла.