如何从目录中删除所有文件的最后一行?

The*_*nix 18 text-processing files

我在一个目录中有很多文本文件,我想删除目录中每个文件的最后一行。

我该怎么做?

小智 17

如果你有 GNU ,你可以使用这个不错的 oneliner sed

 sed -i '$ d' ./*
Run Code Online (Sandbox Code Playgroud)

它将删除当前目录中每个非隐藏文件的最后一行。Switch -ifor GNUsed表示就地操作,'$ d'命令sed删除最后一行($意思是最后一行,d意思是删除)。

  • 如果文件夹包含常规文件以外的任何内容,例如另一个文件夹,这将引发错误(并且不执行任何操作)... (3认同)

N.I*_*.I. 11

如果目录包含的内容不是常规文件,或者文件名中包含空格/换行符的文件,则其他答案都会出现问题。无论如何,这里都有一些工作:

find "$dir" -type f -exec sed -i '$d' '{}' '+'
Run Code Online (Sandbox Code Playgroud)
  • find "$dir" -type f: 查找目录中的文件 $dir
    • -type f 哪些是常规文件;
    • -exec 对找到的每个文件执行命令
    • sed -i:就地编辑文件;
    • '$d': 删除 ( d) 最后一个 ($ ) 行。
    • '+': 告诉 find 继续添加参数sed(比分别为每个文件运行命令更有效,感谢@zwol)。

如果您不想进入子目录,则可以将参数添加-maxdepth 1find.


Sté*_*las 9

使用 GNUsed -i '$d'意味着读取完整文件并制作一份没有最后一行的副本,而只截断文件(至少对于大文件)会更有效率。

使用 GNU truncate,您可以执行以下操作:

for file in ./*; do
  [ -f "$file" ] &&
    length=$(tail -n 1 "$file" | wc -c) &&
    [ "$length" -gt 0 ] &&
    truncate -s "-$length" "$file"
done
Run Code Online (Sandbox Code Playgroud)

如果文件相对较小,那么效率可能会降低,因为它会为每个文件运行多个命令。

请注意,对于在最后一个换行符之后(在最后一行之后)包含额外字节的文件,或者换句话说,如果它们具有非分隔的最后一行,则根据tail实现,tail -n 1将仅返回那些额外字节(如 GNU tail),或最后(正确分隔)行和那些额外的字节。


don*_*sti 6

更便携的方法:

for f in ./*
do
test -f "$f" && ed -s "$f" <<\IN
d
w
q
IN
done
Run Code Online (Sandbox Code Playgroud)

我不认为这需要任何解释......除了可能在这种情况下d是一样的$d,因为ed默认情况下选择的最后一行。
这不会递归搜索,也不会处理隐藏文件(又名点文件)。
如果您也想编辑这些内容,请参阅如何将 * 与目录中的隐藏文件匹配


小智 5

如果您有权访问vim,则可以使用:

for file in ./*
do
  if [ -f "${file}" ]
  then
    vim -c '$d' -c "wq" "${file}"
  fi
done
Run Code Online (Sandbox Code Playgroud)