我正在尝试编写一个脚本,确保所有文本文件都以换行符结尾。
当我在特定文件夹中运行此命令时:
find . -exec ed -s {} <<< w \;
我得到以下输出:
Newline appended
Newline appended
Newline appended
Newline appended
Newline appended
Newline appended
Newline appended
Newline appended
Newline appended
Newline appended
Newline appended
好的,但是换行符附加到了哪些文件?我在 Git 历史记录中看不到任何更改,那么这些是未跟踪的文件吗?
我还故意从一个文本文件的末尾删除了换行符,并且ed
没有将其添加回来......
答案1
您的命令略有错误,因为<<<
输入重定向(此处为字符串)附加到find
,而不是附加到ed
。
稍微扩展一下你的命令:
find . -type f -exec sh -c '
for pathname do
echo w | ed -s "$pathname"
done' sh {} +
这只会影响当前目录或其下任何位置的常规文件,并且不会尝试使用ed
.请注意,二进制文件也是常规文件,因此我们必须假设您仅在包含文本文件的目录中运行它(以免损坏已编译的可执行文件、图像文件等)
对于批量常规文件,这将调用一个简短的内联 shell 脚本。该脚本将循环遍历 给出的路径名find
,并在 中打开每个路径ed
名,然后立即保存文件。这会将换行符添加到尚未以换行符结尾的文件中。
要获得有关实际修改了哪些文件的提示,请在调用之前打印出路径名ed
。这将输出全部找到路径名,但列表中的一些路径名后面会散布“添加换行符”消息。
find . -type f -exec sh -c '
for pathname do
printf "%s\n" "$pathname"
echo w | ed -s "$pathname"
done' sh {} +
要检测哪些文件实际上被修改了,您可以写入临时文件,将其与原始文件进行比较,如果存在差异,则用临时文件替换原始文件。
find . -type f -exec sh -c '
tmpfile=$(mktemp); trap "rm -f \"$tmpfile\"" EXIT
for pathname do
printf "w %s\n" "$tmpfile" | ed -s "$pathname" 2>/dev/null
if ! cmp -s "$tmpfile" "$pathname"; then
printf "Fixed %s\n" "$pathname"
mv "$tmpfile" "$pathname"
fi
done' sh {} +
这样做的另一个好处是,除了实际修改的文件之外,您不会更新文件上的时间戳。
这也会抑制“添加换行符”消息ed
,并在文件实际被修改时输出自定义消息。
也可以看看: