Reputation: 12371
I have such a need:
In the directory video
, I need to
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;
Here is my directory:
dir
|--- video
| |--- example.mp4
|--- index.html
|--- generateHtml.sh
generateHtml.sh
is just like above.
Here is what it does:
find the example.mp4
file in video
, then cp index.html example.html
and change a string in the example.html
.
It works well.
But now for some path and name of .mp4
files, there are some special characters, such as &
, ,
-
. It doesn't seem that while read
works for these cases.
I've heard that find -exec
can handle all of special characters but I don't know how to use it for this case.
Upvotes: 0
Views: 2046
Reputation: 531325
If you are using bash
4 or later, I wouldn't bother with find
here; a for
loop will be much simpler. Note there is no need to copy the file, then edit it in-place; just redirect the output of the sed
command to the desired file.
for f in video/**/*.mp4; do
[ -f "$f" ] || continue
tmp=$(basename "$f" .mp4).html
sed "s#sceneFilePath:.*#sceneFilePath: \"$f\",#g" index.html > "$tmp"
done
If you don't actually need to recurse into subdirectories of video
, you can simply use for f in video/*.mp4; do
, and the whole thing works not just in earlier versions of bash
, but environment where the shell and sed
are both POSIX-compliant.
Upvotes: 1
Reputation: 295480
See Using Find for detailed discussion.
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
Note:
-print0
is used on the find
end, and IFS= read -r -d ''
is used on the read
end; this ensures that all possible filenames (including names with newlines, including names with leading or trailing whitespace) are supported..mp4
anywhere in the filename with .html
, has been replaced with one which strips .mp4
off the end of the filename, and appends .html
."$myfile"
is quoted in invoking basename
. This was your most substantial immediate bug in the original code, as previously a filename could be split into multiple separate arguments to basename
.$()
is used instead of backticks. This modern (and yes, POSIX-compliant) command substitution syntax can be easily nested and has much clearer semantics for backslash escapes within.sed -i
, which is nonstandard and nonportable (the above was valid for MacOS but not for GNU), is unneeded here; one can skip the cp
and do the transform in-line.Upvotes: 4