【问题标题】:Loop for deleting first line of Multiple Files using Bash Script使用 Bash 脚本删除多个文件的第一行的循环
【发布时间】:2013-11-17 12:11:10
【问题描述】:

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

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

我收到回显消息,但是当我 cat 文件时,什么都没有改变。有什么想法吗?

提前致谢

【问题讨论】:

    标签: bash


    【解决方案1】:

    我收到回显消息,但是当我 cat 文件时没有任何变化。

    因为简单地tailing 不会更改文件。

    您可以使用sed 就地修改文件,但不包括第一行。说

    sed -i '1d' *.data
    

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


    编辑:BSD sed(在 OSX 上)需要 -i 的参数,因此您可以指定一个扩展名来备份旧文件,或者就地编辑文件,例如:

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

    【讨论】:

    • 干杯我试过这个(在一个包含复制文件的测试目录中),我得到了以下输出: sed: 1: "201001010000a.WAH.data": command a expects \ 后跟文本
    • @Marko 看来您没有执行正确的命令。由于您已经将文件复制到新目录,您可以简单地复制/粘贴上述命令。
    • 还是不行,会不会是 OSX 上的sed 有问题?
    • @Marko 提到的命令应该适用于 BSD sed(在 OSX 上可用的那个)。 sed -i '1d' filename 是做什么的(filename 指的是单个文件)?
    • @devnull 这只会从目录中的 1 个文件中删除第一行,而不是所有文件。
    【解决方案2】:

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

    #!/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 的答案。

    【讨论】:

    • 谢谢,这很有效,并且有非常有用的解释。我的代码背后的原因是我想删除带有tail 的行,然后通过将其回显到终端来获得通知,以查看我在完成 1000 多个文件方面的位置.感谢各位cmets使用tail,以后一定会好好使用的。
    【解决方案3】:

    我会这样做:

    #!/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 退出,这通常更安全。

    【讨论】:

      【解决方案4】:

      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 出现在这里只是因为在使用 glob 时应该始终使用它,尤其是在脚本中:如果没有匹配项,它将使 glob 扩展为空;你不想运行带有不受控制的参数的命令。

      接下来,我们循环遍历您的所有文件,并在命令中使用ed

      • 1: 去第一行
      • d:删除那一行
      • wq:写完退出

      ed 的选项:

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

      【讨论】:

        猜你喜欢
        • 2010-09-25
        • 2016-03-20
        • 1970-01-01
        • 2018-01-22
        • 2013-12-20
        • 1970-01-01
        • 1970-01-01
        • 2016-08-17
        • 2013-03-10
        相关资源
        最近更新 更多