为什么我的命令失败了?

时间:2013-05-26 15:41:27

标签: bash sed find

for i in `find `pwd` -name .htaccess -exec grep -q "RedirectMatch" {} \; -print`; do $i | sed -i 's/RedirectMatch/#RedirectMatch/g'; done

所以我的命令应该搜索所有的.htaccess文件并grep其中包含“RedirectMatch”的文件,一旦完成它应该通过管道输出来注释掉该行。

正在运行

find `pwd` -name .htaccess -exec grep -q "RedirectMatch" {} \; -print

实际上给了我一个包含“RedirectMatch”的.htaccess文件的列表,但是当我在我的循环中运行它时会抛出一大堆文件,甚至是那些没有命名的文件.htaccess。

有什么想法吗?感谢所有帮助。

3 个答案:

答案 0 :(得分:2)

这是因为你的反引号:你的命令实际执行find,然后将pwd字符串附加到它,然后尝试并执行其余的。

使用$(...)

for i in $(find $(pwd) -name .htaccess -exec grep -q "RedirectMatch" {} \; -print); do sed -i 's/RedirectMatch/#RedirectMatch/g' $i; done

因为默认情况下find默认情况下在当前目录中查找(如果没有指定),您可以进一步指定它:

for i in $(find -name .htaccess -exec grep -q "RedirectMatch" {} \; -print); do sed -i 's/RedirectMatch/#RedirectMatch/g' $i; done

(编辑:还修复了sed命令的调用)

答案 1 :(得分:0)

该命令出现了一些问题:

首先,你需要逃避嵌套反引号,让它们按你认为的方式工作:

`find \`pwd\` -name .htaccess -exec grep -q "RedirectMatch" {} \; -print`

或使用首选的子shell表示法:

$(find $(pwd) -name .htaccess -exec grep -q "RedirectMatch" {} \; -print)

其次,在使用就地sed标志时,您无法输入-i。我不确定你在这里想要完成什么,但我认为你应该在每个文件上运行sed,如果字符串不在那里,什么都不会被替换,并且它不会有任何低效率。你正在做什么不会以任何方式编辑任何文件,你只是在stdin的文件名上运行sed,而不是文件本身!所以像这样:

find . -name .htaccess -exec sed -i "" 's/RedirectMatch/#RedirectMatch/g' {} \;

注意:-i之后的引号对于sed(在darwin上运行)是必需的,它们满足-i标志对参数的需要,大多数{{}可能不需要1}}秒。另外,正如其他人提到的那样,没有必要调用sed,因此我将其与pwd进行了交换。

答案 2 :(得分:0)

到目前为止给出的答案是危险错误的 - 它们可以被操纵以包含任意输出(想想某人创建一个名称中包含空格的单个文件,例如"./ /etc/passwd /.htaccess",从而导致您的脚本编辑/etc/passwd)。

while IFS='' read -r -d '' filename; do
  sed -i -e 's/^([^#]+)RedirectMatch/\1#RedirectMatch/' "$filename"
done < <(find . -name .htaccess -print0)

但请注意,使用sed -i不可移植 - 在POSIX中未指定-i标志,并且许多操作系统不支持它。您最好使用ex进行编辑,该编辑由POSIX指定,并使用与vi中的命令模式相同的语法进行编辑:

while IFS='' read -r -d '' filename; do
  ex "$filename" -s - <<<'%s/^\([^#]*\)RedirectMatch/\1#RedirectMatch/'$'\n''x'
done < <(find . -name .htaccess -print0)