文件file00
通过file99
(百个文件)命名。它们都在同一个目录中。如何抓取所有一百个文件并删除每个文件的前 10 行?我使用的是 CentOS 7。
答案1
file00
这将从名称范围为到 的所有文件中删除前十行file99
:
sed -i.bak -n '11,$p' file[0-9][0-9]
这可能需要 GNU ,这在 OSX 上sed
被称为。gsed
对于其他 sed,请尝试:
find file[0-9][0-9] -maxdepth 0 -type f -exec sed -i.bak -n '11,$p' {} \;
怎么运行的:
-i.bak
告诉 sed 就地修改文件,创建扩展名为 .bak 的备份文件-n
告诉 sed 不要打印任何行,除非我们明确要求它打印。11,$p
告诉 sed 打印从第 11 行开始到$
文件中最后一行(表示为 )的行。file[0-9][0-9]
是一个 shell glob,它将扩展以匹配名称由file
后跟两位数字组成的所有文件。
选择
逻辑可以颠倒。我们可以(提示:JigglyNaga)删除前十行,而不是显式打印第 11 行及之后的行:
sed -i.bak '1,10d' file[0-9][0-9]
答案2
bash
在(或任何类似 Bourne 的 shell)和 GNU 或 BSD中使用简单循环sed
:
for f in file[0-9][0-9]; do
sed -i '.bak' '1,10d' "$f"
done
编辑sed
脚本1,10d
将从输入流中删除第 1 行到第 10 行。其他行将被输出。我们-i '.bak'
要求sed
在文件中进行内联编辑,但要使用后缀备份原始文件.bak
。
具有显式循环的替代方案(允许子间隔、ksh93
或bash
语法zsh
):
for (( i = 0; i < 100; ++i )); do
f="$( printf "file%02d" "$i" )"
sed -i '.bak' '1,10d' "$f"
done
使用ksh93
or zsh
,另一种方式:
typeset -Z 2 j
for (( i = 0; i < 100; ++i )); do
j=$i
sed -i '.bak' '1,10d' "file$j"
done
将typeset -Z 2 j
强制$j
转换为宽度为 2 的零填充数字。我们不希望typeset
i
以这种方式,因为一旦达到 100,它的值就会变成00
100,从而有效地将循环变成无限循环。这是 for ksh93
,zsh
似乎能够处理它,因为它显然在将其提交到格式化之前使用了该值。
答案3
为了避免创建临时文件或影响文件的权限、所有权或其他属性,请使用ksh93
:
for f in file{2}([0-9]); do
tail -n +11 < "$f" 1<>; "$f"
done
重定向<>;
操作符的作用类似于<>
(以读+写模式打开),不同之处在于 shell 在命令成功退出时在命令离开的位置截断文件。
所以,我们基本上是在覆盖文件本身。
答案4
如果您更喜欢 bash 循环:
for f in file[0-9][0-9]; do
tail -n +11 "$f" > tmp &&
mv -f tmp "$f"
done