Open3
シェルスクリプトでディレクトリ名とファイル名を再帰的に変換する

変換テスト用のディレクトリを用意する
test-dir
┣ bar1
┃ ┣ bar2
┃ ┃ ┣ bar3
┃ ┃ ┃ ┗ bar.txt
┃ ┃ ┗ bar.txt
┃ ┗ bar.txt
┗ foo1
┃ ┣ foo2
┃ ┃ ┣ foo3
┃ ┃ ┃ ┗ foo.txt
┃ ┃ ┗ foo.txt
┃ ┗ foo.txt
シェルスクリプト
rename-r
#!/bin/zsh
# ----------------------------------------------------
# ディレクトリ名とファイル名を再帰的に置換する
# ----------------------------------------------------
# 変換したいルートディレクトリパス
startDir=$1
beforeStrings=$2
afterStrings=$3
if [ -z $startDir ]; then
echo "ディレクトリパスを指定してください"
exit 1
fi
if [ -z $beforeStrings ]; then
echo "置換前の文字列を指定してください"
exit 1
fi
if [ -z $afterStrings ]; then
echo "置換後の文字列を指定してください"
exit 1
fi
# ディレクトリに移動
cd ${startDir}
echo "cd ${startDir}"
# ディレクトリの深さを取得
dirDepth=`find . -type d | awk -F/ '{ print NF }' | sort | tail -1`
echo "dirDepth: $dirDepth"
# ディレクトリの階層を上から順に潜ってリネーム処理をしていく
for dirLevel in $(seq $dirDepth)
do
echo "---------------------------------------------------"
echo "dirLevel: $dirLevel"
# ディレクトリの深さに応じてファイル名を取得
targetNames=`find . -maxdepth $dirLevel -name "*$beforeStrings*"`
if [ -z "$targetNames" ]; then
echo "対象のファイルが見つかりませんでした"
continue
fi
while read targetName; do
# 新しい名前を作成
newName=${targetName//$beforeStrings/$afterStrings}
# 名前を変更
mv $targetName $newName
# 結果を出力
echo "Renamed: $targetName -> $newName"
done <<< "${targetNames}"
done
ディレクトリ構成
my-command
┣ test-dir
┗ rename-r
実行結果
my-command $ rename-r test-dir bar pon
cd test-dir
dirDepth: 4
---------------------------------------------------
dirLevel: 1
Renamed: ./bar1 -> ./pon1
---------------------------------------------------
dirLevel: 2
Renamed: ./pon1/bar2 -> ./pon1/pon2
Renamed: ./pon1/bar.txt -> ./pon1/pon.txt
---------------------------------------------------
dirLevel: 3
Renamed: ./pon1/pon2/bar3 -> ./pon1/pon2/pon3
Renamed: ./pon1/pon2/bar.txt -> ./pon1/pon2/pon.txt
---------------------------------------------------
dirLevel: 4
Renamed: ./pon1/pon2/pon3/bar.txt -> ./pon1/pon2/pon3/pon.txt
bar
が pon
に変更されている。
test-dir
┣ foo1
┃ ┣ foo2
┃ ┃ ┣ foo3
┃ ┃ ┃ ┗ foo.txt
┃ ┃ ┗ foo.txt
┃ ┗ foo.txt
┗ pon1
┃ ┣ pon2
┃ ┃ ┣ pon3
┃ ┃ ┃ ┗ pon.txt
┃ ┃ ┗ pon.txt
┃ ┗ pon.txt

ディレクトリを対象外にしてファイル名のみ変更したい場合
#!/bin/zsh
# ----------------------------------------------------
# ファイル名のみを再帰的に置換する
# ----------------------------------------------------
# 変換したいルートディレクトリパス
startDir=$1
beforeStrings=$2
afterStrings=$3
if [ -z $startDir ]; then
echo "ディレクトリパスを指定してください"
exit 1
fi
if [ -z $beforeStrings ]; then
echo "置換前の文字列を指定してください"
exit 1
fi
if [ -z $afterStrings ]; then
echo "置換後の文字列を指定してください"
exit 1
fi
# ディレクトリに移動
cd ${startDir}
echo "cd ${startDir}"
# ファイル名一覧を取得
targetNames=`find . -type f -name "*$beforeStrings*"`
if [ -z "$targetNames" ]; then
echo "対象のファイルが見つかりませんでした"
return 1
fi
echo "targetNames: ${targetNames}"
while read targetName; do
echo "---------------------------------------------------"
echo "targetName: ${targetName}"
# ディレクトリパスを除いたファイル名を取得
fileName=`echo ${targetName} | awk -F/ '{print $NF}'`
echo "fileName: ${fileName}"
# ディレクトリパスのみを取得
dirName=${targetName%/*}
echo "dirName: ${dirName}"
# 新しいファイル名前を作成
newName=${fileName//$beforeStrings/$afterStrings}
# 新しいフルパス
newFullName=${dirName}/${newName}
echo "newFullName: ${newFullName}"
# 名前を変更
mv $targetName $newFullName
# 結果を出力
echo "Renamed: $targetName -> $newFullName"
done <<< "${targetNames}"
実行結果
my-command $ rename-rf test-dir bar pon
cd test-dir
targetNames: ./bar1/bar2/bar3/bar.txt
./bar1/bar2/bar.txt
./bar1/bar.txt
---------------------------------------------------
targetName: ./bar1/bar2/bar3/bar.txt
fileName: bar.txt
dirName: ./bar1/bar2/bar3
newFullName: ./bar1/bar2/bar3/pon.txt
Renamed: ./bar1/bar2/bar3/bar.txt -> ./bar1/bar2/bar3/pon.txt
---------------------------------------------------
targetName: ./bar1/bar2/bar.txt
fileName: bar.txt
dirName: ./bar1/bar2
newFullName: ./bar1/bar2/pon.txt
Renamed: ./bar1/bar2/bar.txt -> ./bar1/bar2/pon.txt
---------------------------------------------------
targetName: ./bar1/bar.txt
fileName: bar.txt
dirName: ./bar1
newFullName: ./bar1/pon.txt
Renamed: ./bar1/bar.txt -> ./bar1/pon.txt
ファイルのみponに変更されている。
test-dir
┣ bar1
┃ ┣ bar2
┃ ┃ ┣ bar3
┃ ┃ ┃ ┗ pon.txt
┃ ┃ ┗ pon.txt
┃ ┗ pon.txt
┗ foo1
┃ ┣ foo2
┃ ┃ ┣ foo3
┃ ┃ ┃ ┗ foo.txt
┃ ┃ ┗ foo.txt
┃ ┗ foo.txt