我有这样的需要:
在目录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
可以处理所有特殊字符,但我不知道如何在这种情况下使用它。
答案 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
注意:
-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的环境。