複数ディレクトリに渡って、テキストの一括変換
あるディレクトリ配下の全てのディレクトリに含まれるファイルのテキストを一括変換したい。
例えば?、まさに?、あるWebサイトの中のコピーライトの年号を変更したいとか、リンク先を変更したいとか。
アプローチは2つ。
Type A. findで要らないバイナリファイルを排除しながら、ファイル名をゲット。一旦ログに吐いて、必要なファイルだけにsedで一括変換
Type B.途中のログを出さず、findで見つけた全てにsedを実施。
Type Aのfind
#!/bin/bash strings=$1 ## ここではhtm,html,php,cgi,jsだけを対象に、パラメータで指定された文字列を検索してエコー files=$(find ./ -name '*.htm' -o -name '*.html' -o -name '*.php' -o -name '*.cgi' -o -name '*.js' ) for F in ${files} do if ( grep "${strings}" $F > /dev/null ) then echo ${F}, fi done
Type Aの後半
#!/bin/bash strings=$1 newStrings=$2 ## ここは変数にしているが、ファイルを読み込む方が良いよね。 files=( aa/bb.htm aa/cc.html bb/dd.cgi) for F in ${files[*]} do echo ${F} cp $F $F.tmp sed -e "s/${strings}/${newStrings}/g" $F.tmp > $F rm $F.tmp done
ファイル読み込みの場合(検索文字 ファイル名をパラメータに指定する)
#!/bin/bash files=$(cat $2) strings=$1 while read F do echo ${F} cp $F $F.tmp sed -e "s/${strings}/${newStrings}/g" $F.tmp > $F rm $F.tmp done <<< "${files}"
Type Bの場合
#!/bin/bash #こちらは、排除したいファイル名を羅列している。 files=$(find ./ ! -name '*.bak' -a ! -name '*.txt' -a ! -name '*.dat' -a ! -name '*.jpg' -a ! -name '*.pdf' -a ! -name 'back*' ) strings=$1 newStrings=$2 for F in ${files} do if ( grep "${strings}" $F > /dev/null ) then part=$(grep "${strings}" $F) echo ${F} " : " ${part} cp ${F} ${F}.tmp sed -e "s/${strings}/${newStrings}/g" ${F}.tmp >${F} rm ${F}.tmp fi done