向 *.cpp 和 *.h(或任何指定的文件类型)添加换行符的 bash 命令?

A bash command that adds newlines to *.cpp and *.h (or any specified filetypes)?

我试过了运行

echo "\n" >> *.cpp *.h

但是我得到了

*.cpp: Ambiguous.

一个简单的命令就可以了,但是如果它只将它添加到已经不以换行符结尾的非空文件中,则会增加奖励

虽然没有获得任何美妆大奖,但至少它是明确的和实用的,并且完全符合要求(只在非空文件和不以换行符结尾的文件中添加换行符):

for f in *.cpp *.h; do
    if [[ $(tail -c1 "$f"; echo x) =~ [^$'\n']x ]]; then
        echo >> "$f"
    fi
done

解释:

  • tail -c1 "$f" 输出文件的最后一个字符,如果有的话。

  • echo x 是确保保留换行符的 hack。 (从 $() 命令替换中删除尾随换行符。)

  • =~ 与正则表达式 [^\n]x 进行比较,即某些字符(必须有一个字符)不是换行符后跟 x .我们需要 $'\n'(一种 bashism)而不是 \n 来匹配文字换行符。

  • echo >> "$f" 在文件末尾添加一个换行符。 (echo 将打印终止换行符,除非使用 -n 标志。)

更新:

这是一个更简单的版本:

for f in *.cpp *.h; do
    if tail -c1 "$f" | egrep -q .; then
        echo >> "$f"
    fi
done

egrep 逐行匹配,因此不会匹配换行符。因此,正则表达式 . 将匹配任何不是换行符的字符(并且必须有一个字符)。 (管道上的 if 检查管道中最后一个命令的退出状态——在本例中为 egrep-q 使 egrep 无声。)

如果您要尝试确保每个文件都以换行符结尾(而不是以单个空行结尾),那么您可以使用 GNU 或 BSD sed (Posix 标准 sed 不必识别 -i 选项,但大多数会识别):

sed -n -i.bak 'G;P' *.{cc,h}

-n 选项禁止自动打印。 -i.bak 就地编辑,保留扩展名为 .bak 的备份文件。 (如果您不需要备份文件,请提供一个空字符串作为扩展名。)

程序:

G  append a newline and the hold buffer (which is empty)
P  print the pattern space up to the first newline.