【发布时间】: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
一般来说,Bash 脚本和编程是新手。我想自动删除目录中多个 .data 文件的第一行。我的脚本如下:
#!/bin/bash
for f in *.data ;
do tail -n +2 $f | echo "processing $f";
done
我收到回显消息,但是当我 cat 文件时,什么都没有改变。有什么想法吗?
提前致谢
【问题讨论】:
标签: bash
我收到回显消息,但是当我 cat 文件时没有任何变化。
因为简单地tailing 不会更改文件。
您可以使用sed 就地修改文件,但不包括第一行。说
sed -i '1d' *.data
将从所有.data 文件中删除第一行。
编辑:BSD sed(在 OSX 上)需要 -i 的参数,因此您可以指定一个扩展名来备份旧文件,或者就地编辑文件,例如:
sed -i '' '1d' *.data
【讨论】:
sed 有问题?
sed(在 OSX 上可用的那个)。 sed -i '1d' filename 是做什么的(filename 指的是单个文件)?
您没有更改文件本身。通过使用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 命令实现什么。你为什么在那里使用管道(|)?
sed 会给你一个更简单的方法来实现这一点。请参阅 devnull 的答案。
【讨论】:
tail 的行,然后通过将其回显到终端来获得通知,以查看我在完成 1000 多个文件方面的位置.感谢各位cmets使用tail,以后一定会好好使用的。
我会这样做:
#!/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 退出,这通常更安全。
【讨论】:
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 知道在那之后没有更多选项,并且会愉快地处理任何文件,即使是那些以连字符开头的文件。【讨论】: