sed不能正确处理多个输入文件

sed不能正确处理多个输入文件,sed,zsh,Sed,Zsh,sed-i正在创建子目录中所有文件的备份,然后再就地编辑(如预期的那样),但实际上它并没有编辑子目录中的文件 $ mkdir -p a/b $ echo "A" > a/a.txt $ echo "B" > a/b/b.txt 现在我有两个文本文件,一个在a中,一个在a $ sed -i.bac "1s/^/PREPENDED /" a/**/*.txt 为以下两个项目创建备份: $ find a a a/a.txt a/a.txt.bac a/b a/b/b.txt a/b

sed-i
正在创建子目录中所有文件的备份,然后再就地编辑(如预期的那样),但实际上它并没有编辑子目录中的文件

$ mkdir -p a/b
$ echo "A" > a/a.txt
$ echo "B" > a/b/b.txt
现在我有两个文本文件,一个在
a
中,一个在
a

$ sed -i.bac "1s/^/PREPENDED /" a/**/*.txt
为以下两个项目创建备份:

$ find a  
a
a/a.txt
a/a.txt.bac
a/b
a/b/b.txt
a/b/b.txt.bac
仅编辑a.txt文件:

$ cat a/a.txt   
PREPENDED A

$ cat a/b/b.txt 
B
我使用的是ZSH(所以我有globstar支持),我使用的是Mac


为什么会发生这种情况以及我如何修复它?

之所以会发生这种情况,是因为您的sed调用只有一行1,它恰好位于
a.txt
中。如果希望它为每个文件执行此操作,则需要多次调用sed

for f in a/**/*.txt
do
  sed ... "$f"
done

由于您需要遍历多个级别的目录,仅调用
sed
是不够的。但是,使用
find
可以在一行中完成您想要的内容。如果您不熟悉
查找-exec'{}'\值得花上几分钟时间进行快速搜索。在您的情况下,以下调用运行良好:

find a -type f -name "*.txt" -exec sed -i.bac 's/^/PREPENDED /' '{}' \;
这里
find
搜索目录
a
和下面所有匹配
*.txt
的文件(
-type f
),然后搜索每个文件(由
'{}'
指示)
-exec
执行
sed-i.bac/^/prepend/'
,最后执行一个转义的
用于指示
-exec
命令的结束

结果:

$ ls -1 a
b
a.txt
a.txt.bac

$ ls -1 a/b
b.txt
b.txt.bac

$ cat a/a.txt
PREPENDED A

$ cat a/b/b.txt
PREPENDED B
正如正确指出的那样,使用globstar set
shopt-s globstar
时,不需要使用
find
,因为以下调用
sed
就足够了:

 sed -i.bac 's/^/PREPENDED /' a/**/*.txt

如果您使用的是zsh,为什么要标记这个问题?Bash 4支持globstar。globstar处理降序目录;对于基于globstar的答案,无需调用
find
。Accepted。我所需要的只是删除
1
@Jake:只有在所有输入文件都只有一行的情况下,这才有效。如果是这种情况,请更新您的问题,说明。@mklement0:谢谢,我的文件不止一行。基于
查找
的解决方案有效。+1;换言之:
sed
总是在所有输入文件中累计计算行号,因此地址
1
仅与第一个输入文件中的第一行匹配(与
awk
相反,除了累积
NR
计数器外,它还为每个输入文件行号提供了一个
FNR
计数器)。