2024-08-21 09:00:02

修改多个文件

下面的命令正确地更改了2个文件的内容。

sed -i 's/abc/xyz/g' xaa1 xab1 

但是我需要动态更改几个这样的文件,我不知道文件名。我想写一个命令,将读取当前目录下以xa*开头的所有文件,sed应该改变文件内容。


当前回答

我很惊讶没有人提到-exec参数来查找,这是为这种类型的用例准备的,尽管它将为每个匹配的文件名启动一个进程:

find . -type f -name 'xa*' -exec sed -i 's/asd/dsg/g' {} \;

或者,也可以使用xargs,这样可以调用更少的进程:

find . -type f -name 'xa*' | xargs sed -i 's/asd/dsg/g'

或者更简单地使用+ exec变体而不是;在find中允许find为每个子进程调用提供多个文件:

find . -type f -name 'xa*' -exec sed -i 's/asd/dsg/g' {} +

其他回答

我使用find来完成类似的任务。这很简单:你必须像这样将它作为sed的参数传递:

sed -i 's/EXPRESSION/REPLACEMENT/g' ' find -name "文件。正则表达式”

这样就不需要编写复杂的循环,而且很容易看出要更改哪些文件,只需在运行sed之前运行find即可。

@PaulR将此作为评论发布,但人们应该将其视为一个答案(这个答案最符合我的需求):

sed -i 's/abc/xyz/g' xa*

这将适用于中等数量的文件,可能是几十个,但可能不是几百万个。

这些命令在Mac OS X自带的默认sed中不起作用。

来自男人1 sed:

-i extension
             Edit files in-place, saving backups with the specified
             extension.  If a zero-length extension is given, no backup 
             will be saved.  It is not recommended to give a zero-length
             extension when in-place editing files, as you risk corruption
             or partial content in situations where disk space is exhausted, etc.

试着

sed -i '.bak' 's/old/new/g' logfile*

and

for i in logfile*; do sed -i '.bak' 's/old/new/g' $i; done

两者都工作得很好。

我很惊讶没有人提到-exec参数来查找,这是为这种类型的用例准备的,尽管它将为每个匹配的文件名启动一个进程:

find . -type f -name 'xa*' -exec sed -i 's/asd/dsg/g' {} \;

或者,也可以使用xargs,这样可以调用更少的进程:

find . -type f -name 'xa*' | xargs sed -i 's/asd/dsg/g'

或者更简单地使用+ exec变体而不是;在find中允许find为每个子进程调用提供多个文件:

find . -type f -name 'xa*' -exec sed -i 's/asd/dsg/g' {} +

上面有一些很好的答案。我想我要再加上一个简洁且可并行的方法,使用GNU并行,我通常更喜欢xargs:

parallel sed -i 's/abc/xyz/g' {} ::: xa*

将此选项与-j N选项结合起来,可以并行运行N个作业。