下面的命令正确地更改了2个文件的内容。
sed -i 's/abc/xyz/g' xaa1 xab1
但是我需要动态更改几个这样的文件,我不知道文件名。我想写一个命令,将读取当前目录下以xa*开头的所有文件,sed应该改变文件内容。
下面的命令正确地更改了2个文件的内容。
sed -i 's/abc/xyz/g' xaa1 xab1
但是我需要动态更改几个这样的文件,我不知道文件名。我想写一个命令,将读取当前目录下以xa*开头的所有文件,sed应该改变文件内容。
当前回答
另一种更通用的方法是使用find:
sed -i 's/asd/dsg/g' $(find . -type f -name 'xa*')
其他回答
上面有一些很好的答案。我想我要再加上一个简洁且可并行的方法,使用GNU并行,我通常更喜欢xargs:
parallel sed -i 's/abc/xyz/g' {} ::: xa*
将此选项与-j N选项结合起来,可以并行运行N个作业。
更好的是:
for i in xa*; do
sed -i 's/asd/dfg/g' $i
done
因为没有人知道有多少文件,而且很容易打破命令行限制。
下面是当文件太多时会发生的情况:
# grep -c aaa *
-bash: /bin/grep: Argument list too long
# for i in *; do grep -c aaa $i; done
0
... (output skipped)
#
另一种更通用的方法是使用find:
sed -i 's/asd/dsg/g' $(find . -type f -name 'xa*')
如果你能够运行一个脚本,下面是我对类似情况所做的:
使用字典/hashMap(关联数组)和sed命令的变量,我们可以遍历数组来替换几个字符串。在name_pattern中包含一个通配符将允许在指定目录(source_dir)中替换文件中的模式(这可能是类似name_pattern='File*.txt')。 所有更改都写在destin_dir的日志文件中
#!/bin/bash
source_dir=source_path
destin_dir=destin_path
logfile='sedOutput.txt'
name_pattern='File.txt'
echo "--Begin $(date)--" | tee -a $destin_dir/$logfile
echo "Source_DIR=$source_dir destin_DIR=$destin_dir "
declare -A pairs=(
['WHAT1']='FOR1'
['OTHER_string_to replace']='string replaced'
)
for i in "${!pairs[@]}"; do
j=${pairs[$i]}
echo "[$i]=$j"
replace_what=$i
replace_for=$j
echo " "
echo "Replace: $replace_what for: $replace_for"
find $source_dir -name $name_pattern | xargs sed -i "s/$replace_what/$replace_for/g"
find $source_dir -name $name_pattern | xargs -I{} grep -n "$replace_for" {} /dev/null | tee -a $destin_dir/$logfile
done
echo " "
echo "----End $(date)---" | tee -a $destin_dir/$logfile
First, the pairs array is declared, each pair is a replacement string, then WHAT1 will be replaced for FOR1 and OTHER_string_to replace will be replaced for string replaced in the file File.txt. In the loop the array is read, the first member of the pair is retrieved as replace_what=$i and the second as replace_for=$j. The find command searches in the directory the filename (that may contain a wildcard) and the sed -i command replaces in the same file(s) what was previously defined. Finally I added a grep redirected to the logfile to log the changes made in the file(s).
这在GNU Bash 4.3 sed 4.2.2中为我工作,并基于VasyaNovikov对Bash中元组循环的回答。
这些命令在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
两者都工作得很好。