2024-08-21 09:00:02

修改多个文件

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

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

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


当前回答

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

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

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

其他回答

我很惊讶没有人提到-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个作业。

银色搜索者解决方案

我为那些不知道名为Silver Searcher(命令行工具是ag)的神奇工具的人添加了另一个选择。

注意:你可以使用grep和其他工具来做同样的事情,但是Silver Searcher很棒:)

TLDR

ag -l 'abc' | xargs sed -i 's/abc/xyz/g'

安装银色搜索器

sudo apt install silversearcher-ag                # Debian / Ubuntu
sudo pacman -S the_silver_searcher                # Arch / EndeavourOS
sudo yum install epel-release the_silver_searcher # RHEL / CentOS

演示文件

将以下内容粘贴到您的终端以创建一些演示文件:

mkdir /tmp/food
cd /tmp/food
content="Everybody loves to abc this food!"
echo "$content" > ./milk
echo "$content" > ./bread
mkdir ./fastfood
echo "$content" > ./fastfood/pizza
echo "$content" > ./fastfood/burger
mkdir ./fruit
echo "$content" > ./fruit/apple
echo "$content" > ./fruit/apricot

使用“ag)”

下面的ag命令将递归地找到包含字符串'abc'的所有文件。它会忽略.git目录、.gitignore文件和其他忽略文件:

$ ag 'abc'
milk
1:Everybody loves to abc this food!

bread
1:Everybody loves to abc this food!

fastfood/burger
1:Everybody loves to abc this food!

fastfood/pizza
1:Everybody loves to abc this food!

fruit/apple
1:Everybody loves to abc this food!

fruit/apricot
1:Everybody loves to abc this food!

只列出包含字符串'abc'的文件,使用-l开关:

$ ag -l 'abc'
bread
fastfood/burger
fastfood/pizza
fruit/apricot
milk
fruit/apple

修改多个文件

最后,使用xargs和sed,我们可以用另一个字符串替换'abc'字符串:

ag -l 'abc' | xargs sed -i 's/abc/eat/g'

在上面的命令中,ag列出了包含字符串'abc'的所有文件。xargs命令分割文件名,并将它们分别输送到sed命令中。

你能使

你搜索'xxxx'文本,并将其替换为'yyyy'

grep -Rn '**xxxx**' /path | awk -F: '{print $1}' | xargs sed -i 's/**xxxx**/**yyyy**/'

您可以同时使用grep和sed。这允许您递归地搜索子目录。

Linux: grep -r -l <old> * | xargs sed -i 's/<old>/<new>/g'
OS X: grep -r -l <old> * | xargs sed -i '' 's/<old>/<new>/g'

For grep:
    -r recursively searches subdirectories 
    -l prints file names that contain matches
For sed:
    -i extension (Note: An argument needs to be provided on OS X)