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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/20030506/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-18 08:39:22  来源:igfitidea点击:

Loop for deleting first line of Multiple Files using Bash Script

bash

提问by Marko

Just new to Bash scripting and programming in general. I would like to automate the deletion of the first line of multiple .data files in a directory. My script is as follows:

刚开始接触 Bash 脚本和编程。我想自动删除目录中多个 .data 文件的第一行。我的脚本如下:

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

I get the echo message but when I cat the file nothing has changed. Any ideas?

我收到回显消息,但是当我发现文件时,没有任何变化。有任何想法吗?

Thanks in advance

提前致谢

采纳答案by pfnuesel

You are not changing the file itself. By using tailyou simply read the file and print parts of it to stdout(the terminal), you have to redirect that output to a temporary file and then overwrite the original file with the temporary one.

您没有更改文件本身。通过使用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

Moreover it's not clear what you'd like to achieve with the echocommand. Why do you use a pipe (|) there?

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

sedwill give you an easier way to achieve this. See devnull's answer.

sed将为您提供一种更简单的方法来实现这一目标。请参阅 devnull 的答案。

回答by devnull

I get the echo message but when I cat the file nothing has changed.

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

Because simply tailing wouldn't change the file.

因为简单的tailing 不会改变文件。

You could use sedto modify the files in-place with the first line excluded. Saying

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

sed -i '1d' *.data

would delete the first line from all .datafiles.

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



EDIT: BSD sed(on OSX) would expect an argument to -i, so you can either specify an extension to backup older files, or to edit the files in-place, say:

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

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

回答by John Zwinck

I'd do it this way:

我会这样做:

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

If you don't have spongeyou can get it in the moreutilspackage.

如果你没有,sponge你可以把它放在moreutils包里。

The quotes around the filename are important--they will make it work with filenames containing spaces. And the envthing at the top is so that people can set which Bash interpreter they want to use via their PATH, in case someone has a non-default one. The set -eumakes Bash exit if an error occurs, which is usually safer.

文件名周围的引号很重要——它们将使其适用于包含空格的文件名。而env在顶部的事情是让人们可以将其击解释,他们希望通过他们的路径使用,万一有人有一个非默认之一。该set -eu如果发生错误,通常是安全的,使击出。

回答by gniourf_gniourf

edis the standard editor:

ed是标准编辑器:

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

The shopt -s nullglobis here just because you should always use this when using globs, especially in a script: it will make globs expand to nothing if there are no matches; you don't want to run commands with uncontrolled arguments.

之所以shopt -s nullglob在这里只是因为在使用 glob 时应该始终使用它,尤其是在脚本中:如果没有匹配项,它将使 glob 扩展为空;您不想运行带有不受控制的参数的命令。

Next, we loop on all your files, and use edwith the commands:

接下来,我们循环您的所有文件,并使用ed以下命令:

  • 1: go to first line
  • d: delete that line
  • wq: write and quit
  • 1: 转到第一行
  • d: 删除那行
  • wq: 写入并退出

Options for ed:

选项ed

  • -s: tells edto shut up! we don't want edto print its junk on our screen.
  • --: end of options: this will make your script much more robust, in case a file name starts with a hypen: in this case, the hyphen will confuse edtrying to process it as an option. With --, edknows that there are no more options after that and will happily process any files, even those starting with a hyphen.
  • -s: 告诉ed你闭嘴!我们不想ed在我们的屏幕上打印它的垃圾。
  • --: 选项结束:这将使您的脚本更加健壮,以防文件名以连字符开头:在这种情况下,连字符会混淆ed尝试将其作为选项处理。使用--,ed知道此后没有更多选项,并且会很乐意处理任何文件,即使是那些以连字符开头的文件。