循环使用Bash脚本删除多个文件的第一行

时间:2013-11-17 12:11:10

标签: bash

一般都是Bash脚本和编程的新手。我想自动删除目录中多个.data文件的第一行。我的脚本如下:

#!/bin/bash
for f in *.data ;
do tail -n +2 $f | echo "processing $f";
done

我收到回复消息但是当我抓住文件时没有任何改变。有什么想法吗?

提前致谢

4 个答案:

答案 0 :(得分:17)

  

我收到回复消息但是当我抓住文件时没有任何改变。

因为简单tail ing不会更改文件。

您可以使用sed在排除第一行的情况下就地修改文件。说

sed -i '1d' *.data

将从所有.data个文件中删除第一行。


编辑:BSD sed(在OSX上)会期望-i的参数,因此您可以指定扩展来备份旧文件,也可以就地编辑文件,例如:< / p>

sed -i '' '1d' *.data

答案 1 :(得分:3)

您没有更改文件本身。通过使用tail,您只需读取文件并将其部分打印到stdout(终端),您必须将该输出重定向到临时文件,然后使用临时文件覆盖原始文件。 / p>

#!/usr/bin/env bash
for f in *.data; do
    tail -n +2 "$f" > "${f}".tmp && mv "${f}".tmp "$f"
    echo "Processing $f"
done

此外,您不清楚使用echo命令要实现的目标。为什么在那里使用管道(|)?

将为您提供更轻松的方法来实现这一目标。请参阅devnull的回答。

答案 2 :(得分:0)

我这样做:

#!/usr/bin/env bash
set -eu
for f in *.data; do
  echo "processing $f"
  tail -n +2 "$f" | sponge "$f"
done

如果您没有sponge,则可以在moreutils包中找到它。

文件名周围的引号很重要 - 它们可以使用包含空格的文件名。顶部的env是这样的,人们可以设置他们想要通过PATH使用哪个Bash解释器,以防某人有非默认解释器。如果发生错误,set -eu会使Bash退出,这通常更安全。

答案 3 :(得分:0)

ed是标准编辑器:

shopt -s nullglob
for f in *.data; do
    echo "Processing file \`$f'"
    ed -s -- "$f" < <( printf '%s\n' "1d" "wq" )
done

shopt -s nullglob就在这里,因为你在使用globs时应该总是使用它,尤其是在脚本中:如果没有匹配,它会使globs扩展为空;你不想用不受控制的参数运行命令。

接下来,我们循环播放所有文件,并使用ed命令:

  • 1:转到第一行
  • d:删除该行
  • wq:写并退出

ed的选项:

  • -s:告诉ed闭嘴!我们不希望ed在屏幕上打印垃圾。
  • --:选项结束:这将使您的脚本更加健壮,以防文件名以爆炸开头:在这种情况下,连字符会混淆ed尝试将其处理为一个选项。使用--ed知道之后没有其他选项,并且会愉快地处理任何文件,即使是以连字符开头的文件。