【问题标题】:How to loop a shell script across a specific file in all directories?如何在所有目录中的特定文件中循环shell脚本?
【发布时间】:2014-11-18 08:11:22
【问题描述】:

Shell 脚本 sed 错误:

无法查看 /home/xx/htdocs/*/modules/forms/int.php

/bin/rm: 无法删除`/home/xx/htdocs/tmp.26758': 没有这样的文件或目录

我的 shell 脚本出现错误。我不确定这个 for 循环是否有效,它的目的是爬上一个 PHP 文件的大目录树,并在每个 int.php 文件中添加一个函数,并进行一些验证。不要问我为什么这不是集中式/OO,但事实并非如此。我从这里尽可能地复制了脚本:http://www.cyberciti.biz/faq/unix-linux-replace-string-words-in-many-files/

#!/bin/bash
OLD="public function displayFunction(\$int)\n{"
NEW="public function displayFunction(\$int)\n{if(empty(\$int) || !is_numeric(\$int)){return '<p>Invalid ID.</p>';}"
DPATH="/home/xx/htdocs/*/modules/forms/int.php"
BPATH="/home/xx/htdocs/BAK/"
TFILE="/home/xx/htdocs/tmp.$$"
[ ! -d $BPATH ] && mkdir -p $BPATH || :
for f in $DPATH
do 
 if [ -f $f -a -r $f ]; then
   /bin/cp -f $f $BPATH
   sed "s/$OLD/$NEW/g" "$f" > $TFILE && mv $TFILE "$f"
 else
  echo "Error: Cannot view  ${f}"
 fi
done
/bin/rm $TFILE

这样的通配符是否有效?我可以像这样检查树上的每个子目录吗?我需要对数组进行预编码并循环吗?我该怎么做呢?

另外,PHP 代码中的 $ 是否完全破坏了脚本?

我很困惑。

【问题讨论】:

  • 你确定不想要init.php 而不是int.php 吗?否则,可以使用set -vx(或set -x)打开shell 调试功能,查看每个变量使用了哪些值,或者在for f in $DPATH 之后添加echo f=$f。如果.../htdocs 的子目录下有文件module/forms/int.php,我希望* 会扩展。祝你好运。

标签: linux bash shell sed sh


【解决方案1】:

代码中的问题

  • 您不能以这种方式使用 sed 替换多行。
  • 您在 OLD 中使用 /,它在 s/// sed 命令中使用。这行不通
  • [ ! -d $BPATH ] &amp;&amp; mkdir -p $BPATH || : 太可怕了。使用mkdir -p "$bpath" 2&gt;/dev/null
  • 是的,像这样的通配符会起作用,但只是因为你的字符串没有空格
  • Doube-quote 你的变量,否则你的代码会很危险
  • 单引号您的字符串,否则您将无法理解您在转义的内容
  • 不要使用大写的变量名,否则可能会意外替换 bash 内部变量
  • 不要 rm 不存在的文件
  • 您的备份将被覆盖,因为所有文件都命名为 int.php

假设您使用的是 GNU sed,我不习惯其他 sed 风格。 如果您不使用 GNU sed,将 \n 替换为换行符(在字符串内)应该工作。

固定代码

#!/usr/bin/env bash
old='public function displayFunction(\$int)\n{'
old=${old//,/\\,} # escaping eventual commas
# the \$ is for escaping the sed-special meaning of $ in the search field
new='public function displayFunction($int)\n{if(empty($int) || !is_numeric($int)){return "<p>Invalid ID.</p>";}\n'
new=${new//,/\\,} # escaping eventual commas
dpath='/home/xx/htdocs/*/modules/forms/int.php'
for f in $dpath; do 
    [ -r "$f" ]; then
        sed -i.bak ':a;N;$!ba;'"s,$old,$new,g" "$f"
    else
       echo "Error: Cannot view  $f" >&2
    fi
done

链接

【讨论】:

  • 感谢您非常彻底的回答。我最终编写了一个实现反射器类的 php 脚本,但感谢陌生人 :)
猜你喜欢
  • 1970-01-01
  • 2013-10-06
  • 2017-09-18
  • 1970-01-01
  • 1970-01-01
  • 2014-03-01
  • 1970-01-01
  • 1970-01-01
  • 2015-04-10
相关资源
最近更新 更多