一般都是Bash脚本和编程的新手。我想自动删除目录中多个.data文件的第一行。我的脚本如下:
#!/bin/bash
for f in *.data ;
do tail -n +2 $f | echo "processing $f";
done
我收到回复消息但是当我抓住文件时没有任何改变。有什么想法吗?
提前致谢
答案 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
命令要实现的目标。为什么在那里使用管道(|
)?
sed将为您提供更轻松的方法来实现这一目标。请参阅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
知道之后没有其他选项,并且会愉快地处理任何文件,即使是以连字符开头的文件。