ROBOCOPYの堕とし穴
ROBOCOPYの設定値で思いのほか
苦労してしまったので、備忘録メモ。
やりたいこと
簡単のため「Terapad」を例に出すと、
History.txt
Keys.txt
Readme.txt
TeraPad.exe
usr.txt
という5つのファイルが
C:\test\Terapad
というフォルダに入っており、
この「Terapad」フォルダごと
D:\Terapad
として、ROBOCOPYでコピーしたい。
ハマったこと
通常、ROBOCOPYのコマンドは
ROBOCOPY <src> <dest> [<file> <options>]
という指定をする。
上記の「やりたいこと」を実現しようとすると、
ROBOCOPY "C:\test\Terapad" "D:"
でいいのかな、と安易に考えていた。
それが大いなる勘違いだった。
上記のコマンドを実行すると、
Dドライブ直下に
History.txt
Keys.txt
Readme.txt
TeraPad.exe
usr.txt
がブチ撒けられてしまう。
確かに、よくよくROBOCOPYの仕様を
読んでみると、まぁ確かにそうなんだけど。
でもこんな形のコピーは全く望んでいない。
力技で解決
ウンウンと色々悩んだ末に、力技で解決。
諸事情によりPowershellでゴリゴリ記述。
# コピー元のフルパス
$srcpath = "C:\test\Terapad"
# コピー先のフルパス
$dstroot = "D:\"
# オブジェクト種別によってコピーオプション変更
# $srcpathがフォルダかファイルか判定する
$isDir = Get-Item $srcpath | Where-Object{$_.PSIsContainer}
# フォルダの場合
if($isDir){
# 「Terapad」のフォルダ名を取得
$dirname = [System.IO.Path]::GetFileName($srcpath)
# 出力先に「Terapad」フォルダ名を作成
$dstpath = $dstroot + $dirname
New-Item $dstpath -itemType Directory > $null
# 遠慮なくROBOCOPYでブチ撒ける
ROBOCOPY $srcpath $dstpath /E > $null
# ファイルの場合
}else{
# コピー元のファイル名を取得
$filename = [System.IO.Path]::GetFileName($srcpath)
# コピー元の親フォルダを取得
$srcpath = Split-Path $srcpath -parent
# 対象ファイルをブチ撒ける
ROBOCOPY $srcpath $dstroot $filename > $null
}
なお、上記ソースは、コピー元のパスが
ファイルの場合もフォルダの場合も対応している。
うーん。
もっとスマートなやり方が
あるのだろうか…