sed beginner:更改文件夹中的所有实例

nic*_*ckf 78 regex linux shell sed

我需要对文件夹(及其子文件夹)中的所有文件进行正则表达式查找和替换.linux shell命令会做什么?

例如,我想在所有文件上运行它,并使用新的替换文本覆盖旧文件.

sed 's/old text/new text/g' 
Run Code Online (Sandbox Code Playgroud)

osa*_*ana 118

只使用sed无法做到这一点.您至少需要使用find实用程序:

find . -type f -exec sed -i.bak "s/foo/bar/g" {} \;
Run Code Online (Sandbox Code Playgroud)

此命令将为.bak每个更改的文件创建一个文件.

笔记:

  • 命令的-i参数sed是GNU扩展,因此,如果您使用BSD运行此命令,sed则需要将输出重定向到新文件,然后重命名它.
  • find实用程序不在-exec旧的UNIX框中实现该参数,因此,您将需要使用| xargs替代.

  • '\;' 是做什么用的? (7认同)
  • `{}` 将被 `find` 找到的每个文件名替换,而 `\;` 告诉 find 他需要执行的命令此时已完成。 (4认同)
  • 我们需要告诉查找参数-exec的命令以“;”结尾。但是外壳程序使用与外壳程序命令分隔符相同的符号(;),因此,我们需要从外壳程序中转义“;”以将其传递给find的-exec参数。 (3认同)
  • 值得注意的是,“-i”本身不会创建备份文件,而是导致 sed 对文件执行操作的原因。 (3认同)
  • `{}` 是做什么用的? (2认同)

Den*_*nis 39

I prefer to use find | xargs cmd over find -exec because it's easier to remember.

This example globally replaces "foo" with "bar" in .txt files at or below your current directory:

find . -type f -name "*.txt" -print0 | xargs -0 sed -i "s/foo/bar/g"
Run Code Online (Sandbox Code Playgroud)

-print0-0选项可以被排除在外,如果你的文件名不包含时髦的字符,如空格.

  • 如果您使用的是OSX,请尝试"查找".-type f -name"*.txt"-print0 | xargs -0 sed -i''"s/foo/bar/g"`(注意为`-i`参数提供一个空字符串). (2认同)

小智 8

示例:对于 /app/config/ 文件夹及其子文件夹下的所有 ini 文件,内联将 {AutoStart} 替换为 1:

sed -i 's/{AutoStart}/1/g' /app/config/**/*.ini
Run Code Online (Sandbox Code Playgroud)


Nor*_*sey 6

为了便于携带,我不依赖于特定于linux或BSD的sed功能.相反,我使用了overwriteKernighan和Pike在Unix编程环境中的书中的脚本.

然后命令

find /the/folder -type f -exec overwrite '{}' sed 's/old/new/g' {} ';'
Run Code Online (Sandbox Code Playgroud)

overwrite脚本(我在各处使用)是

#!/bin/sh
# overwrite:  copy standard input to output after EOF
# (final version)

# set -x

case $# in
0|1)        echo 'Usage: overwrite file cmd [args]' 1>&2; exit 2
esac

file=$1; shift
new=/tmp/$$.new; old=/tmp/$$.old
trap 'rm -f $new; exit 1' 1 2 15    # clean up files

if "$@" >$new               # collect input
then
    cp $file $old   # save original file
    trap 'trap "" 1 2 15; cp $old $file     # ignore signals
          rm -f $new $old; exit 1' 1 2 15   # during restore
    cp $new $file
else
    echo "overwrite: $1 failed, $file unchanged" 1>&2
    exit 1
fi
rm -f $new $old
Run Code Online (Sandbox Code Playgroud)

这个想法是只有在命令成功时它才会覆盖文件.find在您不想使用的地方也有用

sed 's/old/new/g' file > file  # THIS CODE DOES NOT WORK
Run Code Online (Sandbox Code Playgroud)

因为shell在sed读取之前会截断文件.