我有一个文件列表,我想检查一个特定的string。 如果string存在于文件中,我想用新版本replace它。 什么是最简单的方法呢?
for file in "`grep -l "foo" bar gazi`"; do cp -p --backup=numbered replace "$file"; done
replace是replace文件的path, bar和gazi表示要检查的文件列表,而foo是感兴趣的searchstring。
如果你需要额外的帮助,为grep(上面)制定一个适当的正则expression式,请不要犹豫,问。
grep可以search一个string的文件,如果发现它会返回0,你可以用它作为条件的一部分来replace文件,如下所示:
#!/bin/bash if [ !`/bin/grep -q teststring /path/to/file` ]; then cp newfile oldfile fi
大概你有一个文件列表中的文件? 我不知道你是否有一个静态文件,你正在replace匹配的文件,或每个文件的潜在替代品。 这处理第二种情况,第一种情况下,只是用静态文件名replace$ i.new。
for i in `cat /var/tmp/listoffiles` ; do if grep string $i > /dev/null 2>&1 ; then cp $i $i.old cp $i.new $i fi done
虽然我同意所有的greptesting,但是sed可以在没有testing的情况下做到这一点。
sed -i.BACKUP's / STRING您想要更换/ NEW STRING /'文件
如果string不在那里,它不会做任何事情。 值得一提的是 从你的问题,我不知道你是否试图更换整个文件或只是一个string。
在shell脚本中循环处理文件的正确方法是将命令放入while或将文件redirect到while循环的done语句。 这将处理除包含换行符之外的任何名称。 你不应该for f in $(cmd)使用for f in $(cmd)的forms。
在这个例子中, find是产生文件列表的命令:
find . -type f -name "*.txt" | while read -r filename do if grep -qs "$string" "$filename" # or use >/dev/null 2>&1 instead of -qs then cp "$replacement" "$filename" fi done
或者,这里列表包含在一个文件中:
while read -r filename ... done < "$file_with_list"
另一种方法是使用xargs 。
对于生成文件列表的命令(例如find ):
find . -type f -name "*.txt" -print0 | xargs -0 -I % env string=$string sh 'grep -qs "$string" "%" && cp replacement_file "%"'
前面的方法在文件名可能包含换行符的情况下工作。
如果列表在一个文件中:
xargs -a "$file_with_list" -I % env string=$string sh 'grep -qs "$string" "%" && cp replacement "%"'
所有这些例子都适用于文件名可能包含空格的情况。