Я нашел их в<sys/mode.h>
:
/*
* (stat) st_mode bit values
*/
#define _S_IFMT 0170000 /* type of file */
#define _S_IFREG 0100000 /* regular */
#define _S_IFDIR 0040000 /* directory */
#define _S_IFBLK 0060000 /* block special */
#define _S_IFCHR 0020000 /* character special */
#define _S_IFIFO 0010000 /* fifo */
Первая '1' указывает на обычный файл.
Каталог имеет 240755
, «4» указывает на каталог, а «2» означает «не обычный файл».
Это решение исправляет все неверные заголовки.
sed -r '
:loop; N; $!b loop
s/\n+(#[^\n]+)/\n\n\1/g
s/(#[^\n]+)\n+/\1\n\n/g
s/\n+(#[^\n#]+)/\n\n\n\1/g
' input.txt;
С комментариями:
sed -r '
### put all file into the pattern space,
# in other words, merge all lines into one line
:loop; N; $!b loop;
### first traversal of the pattern space
# searches the line with "#" sign (all cases matches - Titles, SubTitles, etc),
# takes all its upper empty lines
# and converts them to the one empty line
s/\n+(#[^\n]+)/\n\n\1/g;
### second traversal of the pattern space
# again, searches the line with "#" sign, take all its bottom empty lines
# and converts them to the one empty line
s/(#[^\n]+)\n+/\1\n\n/g;
### third traversal of the pattern space
# searches the single "#" sign (Titles only),
# takes all its upper newlines (at this moment only two of them are there,
# because of previous substitutions)
# and converts them to three newlines
s/\n+(#[^\n#]+)/\n\n\n\1/g
' input.txt
Вход
text
# Title
## SubTitle
### SubSubTitle
# Title
## SubTitle
text
### SubSubTitle
# Title
# Title
# Title
## SubTitle
### SubSubTitle
Выход
text
# Title
## SubTitle
### SubSubTitle
# Title
## SubTitle
text
### SubSubTitle
# Title
# Title
# Title
## SubTitle
### SubSubTitle