我正在研究一个bash脚本,它会搜索一个特定的文件,使用通配符路径进行搜索,一旦找到该文件名,它会在文件中搜索特定的术语,然后替换它。
这就是我已经把它放在一起的东西:
#!/bin/sh
PATH=${1}
FILENAME="$2"
SEARCHFOR="$3"
/usr/bin/clear
echo "Searching $PATH"
echo "For the file $FILENAME"
echo "With the string $SEARCHFOR"
echo "=========================="
echo " RESULTS "
echo "=========================="
/usr/bin/find $PATH -type f -name "$FILENAME" | /usr/bin/xargs /bin/grep -l "$SEARCHFOR"
我还没有添加替换品,但我想我会使用SED代替grep来做这件事,只是使用grep进行测试。
使用上面的代码,我必须为任何类型的通配符路径使用引号。有办法解决这个问题吗?
./script '/home/*/public_html' php.ini module.so
我在考虑使用参数,但必须采用另一种方法。
我的最终目标是拥有一个bash脚本,我可以传递通配符路径或文件名,它会搜索该文件,一旦找到它搜索特定术语的文件,并在找到时替换它。
听起来很简单,应该是这样,但是我正撞在桌子上,因为我已经被打扰了很长时间......我帮忙了!
答案 0 :(得分:2)
首先,以大写形式声明变量名称是一个坏的,坏的,非常糟糕的主意,尤其是PATH
,因为你实际上是在重新设置实际的PATH
环境变量(只是在提示符中执行echo $PATH
,您就会理解我的意思,这可能是您必须使用/usr/bin/clear
代替clear
的原因之一,因为env变量{{1得到修改)。因此,始终建议使用小写的变量,如PATH
。
您遇到的问题是子shell中path
扩展glob
。当你使用
*
./script '/home/*/public_html' php.ini module.so
未在提示符处展开(父shell),但在脚本的子shell中展开。但是当你使用
*
./script /home/*/public_html php.ini module.so
在父shell中展开(这会导致shell指向一个随机路径),然后在程序子shell中传递 -
让我们说,*
有目录/home
,/user
,/apps
执行/data
会将您带到按字母顺序排列的目录,即{{ 1}}。因此,父shell中没有引号的$ cd *
将始终指向/apps
,这不是我们想要的!
立即采取补救措施如下
/home/*
或
/home/apps
尝试$set -o noglob #unset glob expansion
$./script /home/*/public_html php.ini module.so #your command without quotes & wildcard */
$set +o noglob #re-set glob expansion back
然后$set -o noglob;./script /home/*/public_html php.ini module.so;set +o noglob
以获得快速示例。
警告 - 如果您失败或忘记将$echo *
设置回$set -o noglob;echo *;set +o noglob
),则shell会处理noglob
和set +o noglob
等字符像普通字符一样,不会扩展它们,这可能会导致不良结果和混乱。
答案 1 :(得分:2)
find $path -name \*$filenamepattern\* -exec sed -i.bak 's/find/replace/g' {} ';'
答案 2 :(得分:1)
只需重新排序您的参数,并在最后放置您要搜索的目录列表。所以:
#!/bin/sh
FILENAME="${1?No filename specified}"
SEARCHFOR="${2?No target string given}"
shift; shift;
SEARCHPATH="$@"
然后你应该能够保持其余的不变(除了将名称PATH更改为SEARCHPATH,因为更改PATH是一个非常糟糕的主意)并将其命名为:
$ ./script php.ini module.so /home/*/public_html
答案 3 :(得分:0)
find `filepath` -name `filename`|xargs sed 's/find/replace/'
对我来说,我会用find和sed来完成这项工作。
答案 4 :(得分:0)
这将解决将通配符传递给bash脚本的问题但请遵守第一个要点。
#!/bin/bash -f
directory=$1
filename=$2
searchfor=$3
replacement=$4
sedpattern=s/$searchfor/$replacement/g
find $directory -name $filename -exec sed -i.bak $sedpattern {} ';'
% ./thisscript . \*.csv oldword newword