如何使用find和exec执行多个命令

时间:2017-05-09 15:24:44

标签: linux bash shell

我有这样的需要:
在目录video中,我需要

find ./video -type f | while read myfile; do
    tmp=`basename $myfile`   #example.mp4
    tmp="${tmp/.mp4/.html}"  #example.html
    cp index.html "$tmp"
    sed -i '' "s#sceneFilePath:.*#sceneFilePath: \"$myfile\",#g" $tmp
#done;

这是我的目录:

dir
 |--- video
 |     |--- example.mp4
 |--- index.html
 |--- generateHtml.sh

generateHtml.sh就像上面一样 这是它的作用:
example.mp4中找到video文件,然后在cp index.html example.html找到并更改example.html中的字符串。

效果很好。

但是现在对于.mp4文件的某些路径和名称,有一些特殊字符,例如&-while read似乎不适用于这些案件。

我听说find -exec可以处理所有特殊字符,但我不知道如何在这种情况下使用它。

2 个答案:

答案 0 :(得分:4)

有关详细讨论,请参阅Using Find

find ./video -type f -print0 | while IFS= read -r -d '' myfile; do
    tmp=$(basename "$myfile")   #example.mp4  -- consider also tmp=${myfile##*/}
    tmp="${tmp%.mp4}.html"      #example.html
    sed "s#sceneFilePath:.*#sceneFilePath: \"$myfile\",#g" \
      <index.html >"$tmp"
done

注意:

    {li> -print0用于find端,IFS= read -r -d ''用于read端;这可确保支持所有可能的文件名(包括带有换行符的名称,包括带有前导或尾随空格的名称)。
  • 之前的替换,用.mp4替换了文件名中任意位置的.html第一个实例,已被替换为剥离.mp4的替换。文件名结尾,并附加.html
  • 在引用"$myfile"时引用了
  • basename。这是原始代码中最重要的直接错误,因为之前的文件名可以分成多个单独的basename参数。
  • 使用
  • $()代替反引号。这种现代(并且是符合POSIX的)命令替换语法可以很容易地嵌套,并且对于反斜杠转义具有更清晰的语义。
  • sed -i,这是非标准且不可移植的(以上对MacOS有效但对GNU无效),这里不需要;可以跳过cp并在线进行转换。

答案 1 :(得分:1)

如果您使用的是bash 4或更高版本,我不会在这里打扰find;一个for循环会简单得多。注意,不需要复制文件,然后就地编辑它;只需将sed命令的输出重定向到所需的文件。

for f in video/**/*.mp4; do
  [ -f "$f" ] || continue
  tmp=$(basename "$f" .mp4).html
  sed "s#sceneFilePath:.*#sceneFilePath: \"$f\",#g" index.html >  "$tmp"
done

如果您实际上不需要递归到video的子目录中,您可以简单地使用for f in video/*.mp4; do,整个事情不仅适用于早期版本的bash,但是shell和sed都符合POSIX的环境。