はじめに
- 必要に迫られ、
/hoge/fuga/moto
配下にあるファイル群を/hoge/fuga
に移動するPythonスクリプトを作成 - 移動前、後の証跡をCSV形式で残す
- CSVファイルは、BOM付きのUTF-8
- ↑ エクセルで開いても文字化けしない対策
スクリプトの引数説明
-
-h
でヘルプ表示 -
-s
-d
は必須オプション - 実行ログ(拡張子
.csv
)は、カレントディレクトに出力。
# /hoge/fuga/moto->/hoge/fugaに移動する場合
$ python3 mv-python3.py -s /hoge/fuga/moto -d /hoge/fuga
# -h でヘルプ表示
$ python3 mv-python3.py -h
usage: mv2.py [-h] -s SRCDIR -d DSTDIR
移動元ディレクトリ内のファイルを移動先ディレクトリに移動する。移動後、移動元ディレクトリを削除する。
optional arguments:
-h, --help show this help message and exit
-s SRCDIR, --srcdir SRCDIR
移動元ディレクトリ
-d DSTDIR, --dstdir DSTDIR
移動先ディレクトリ
# 必須オプションを指定しないとファイル移動しない
$ python3 mv-python3.py
usage: mv-python3.py [-h] -s SRCDIR -d DSTDIR
mv-python3.py: error: the following arguments are required: -s/--srcdir, -d/--dstdir
スクリプト
作成したスクリプト
mv-python3.py
import glob
import os
import datetime
import time
import argparse
import sys
import shutil
parser = argparse.ArgumentParser(description='移動元ディレクトリ内のファイルを移動先ディレクトリに移動する。移動後、移動元ディレクトリを削除する。')
parser.add_argument('-s','--srcdir', required=True, type=str, help='移動元ディレクトリ')
parser.add_argument('-d','--dstdir', required=True, type=str, help='移動先ディレクトリ')
args = parser.parse_args()
srcdir = args.srcdir
dstdir = args.dstdir
# 最後の文字列が / (スラッシュ) なら削除
srcdir = srcdir.rstrip('/')
dstdir = dstdir.rstrip('/')
# ログファイル名を設定
dt_now = datetime.datetime.now()
logFileName = "./log-" + dt_now.strftime('%Y%m%d-%H%M%S') + ".csv"
# ファイルを一覧表示
def resouceList( tgtTitle, curPath ):
curPath += "/*"
resouces = glob.glob(curPath)
resType = ""
for resouce in resouces :
if os.path.isfile(resouce) :
resType = "[FILE]"
resSize=os.path.getsize(resouce)
resMtime=datetime.datetime.fromtimestamp(os.path.getmtime(resouce))
log_list=[tgtTitle, resType, resouce, str(resSize), str(resMtime)]
setlog( log_list, "PF" )
else:
resType = "[DIRECTORY]"
nxtPath = resouce
log_list=[tgtTitle, resType, resouce]
setlog( log_list, "PF" )
resouceList( tgtTitle , nxtPath )
# ファイル/ディレクトリを削除。ただし、移動元ディレクトリは削除しない
def resouceDelete(tgtTitle, exPath, curPath):
curPath += "/*"
resouces = glob.glob(curPath)
resType = ""
skpFlg = 0
for resouce in resouces :
print("src:{0}\ndst:{1}".format(exPath, resouce) )
if exPath == resouce :
skpFlg = 1
if skpFlg == 0 :
if os.path.isfile(resouce) :
resType = "[FILE]"
os.remove(resouce) # DELETE FILE
else:
resType = "[DIRECTORY]"
shutil.rmtree(resouce) # DELETE DIRECTORY
else :
resType = "[NOT-DELETE]"
skpFlg = 0
log_list = [tgtTitle, resType, resouce]
setlog( log_list, "PF" )
# 標準出力、ログ出力
def setlog(log_list, logFlg):
log_dt = datetime.datetime.now().strftime('%Y%m%d-%H%M%S')
log_list.insert(0, log_dt)
log_str=','.join(log_list)
if "P" in logFlg :
print(log_str)
if "F" in logFlg :
f.writelines("{0}\n".format(log_str) )
# ファイル/ディレクトリを移動
def moveResource( tgtTitle, src_dir , dst_dir ):
for p in os.listdir(src_dir):
shutil.move(os.path.join(src_dir, p), dst_dir)
log_list = [tgtTitle, os.path.join(src_dir, p), dst_dir]
setlog( log_list, "PF" )
# 移動元ディレクトリを削除
def sourceDelete( tgtTitle, srcPath) :
shutil.rmtree(srcPath) # DELETE DIRECTORY
log_list = [tgtTitle, srcPath]
setlog( log_list, "PF" )
##------------------------------##
## ROOT FLOW
##------------------------------##
with open( logFileName , 'w' , encoding="utf_8_sig") as f:
resouceList ( "[Step01/08-BEFORE|SOURCE]" , srcdir) # (現状確認)移動元ディレクトリのファイル一覧を表示
resouceList ( "[Step02/08-BEFORE|DISTINATION]" , dstdir) # (現状確認)移動先ディレクトリのファイル一覧を表示
resouceDelete( "[Step03/08-DELETE|DISTINATION]" , srcdir, dstdir) # 移動先ディレクトリ配下のファイルを削除する
resouceList ( "[Step04/08-DELETE-AFTER|DISTINATION]" , dstdir) # (削除確認)移動先ディレクトリのファイル一覧を表示
moveResource ( "[Step05/08-MOVE|DISTINATION]" , srcdir , dstdir ) # 移動元ディレクトリ配下のファイルを移動先ディレクトリに移動
resouceList ( "[Step06/08-AFTER|SOURCE]" , srcdir) # (移動確認)移動元ディレクトリのファイル一覧を表示
resouceList ( "[Step07/08-AFTER|DISTINATION]" , dstdir) # (移動確認)移動先ディレクトリのファイル一覧を表示
sourceDelete ( "[Step08/08-DELETE|SOURCE]" , srcdir) # 移動元ディレクトリを削除
setlog( ["SCRIPT-DONE"], "PF" ) # スクリプト終了をログに記録
f.close()
print("\n|--- DONE ---|\n")
実行例
以下の状態で、…/hoge/fuga
-> …/hoge
に移動してみる
~/data/python/temp/hoge $ tree
.
├── fileA.txt
├── fileB.txt
├── fileC.txt
└── fuga
├── fileA.txt
└── fileB.txt
1 directory, 5 files
スクリプト実行
$ python3 mv-python3.py -s '/home/pi/data/python/temp/hoge/fuga' -d '/home/pi/data/python/temp/hoge'
20200725-144112,[Step01/08-BEFORE|SOURCE],[FILE],/home/pi/data/python/temp/hoge/fuga/fileB.txt,8,2020-07-24 09:29:09.405717
20200725-144112,[Step01/08-BEFORE|SOURCE],[FILE],/home/pi/data/python/temp/hoge/fuga/fileA.txt,8,2020-07-24
<省略>
スクリプト実行後の状態
~/data/python/temp/hoge $ tree
.
├── fileA.txt
└── fileB.txt
0 directories, 2 files
ログファイル
log-20200725-144112.csv
20200725-144112,[Step01/08-BEFORE|SOURCE],[FILE],/home/pi/data/python/temp/hoge/fuga/fileB.txt,8,2020-07-24 09:29:09.405717
20200725-144112,[Step01/08-BEFORE|SOURCE],[FILE],/home/pi/data/python/temp/hoge/fuga/fileA.txt,8,2020-07-24 09:29:09.405717
20200725-144112,[Step02/08-BEFORE|DISTINATION],[FILE],/home/pi/data/python/temp/hoge/fileB.txt,8,2020-07-24 09:29:09.405717
20200725-144112,[Step02/08-BEFORE|DISTINATION],[FILE],/home/pi/data/python/temp/hoge/fileC.txt,8,2020-07-24 09:29:09.405717
20200725-144112,[Step02/08-BEFORE|DISTINATION],[FILE],/home/pi/data/python/temp/hoge/fileA.txt,8,2020-07-24 09:29:09.405717
20200725-144112,[Step02/08-BEFORE|DISTINATION],[DIRECTORY],/home/pi/data/python/temp/hoge/fuga
20200725-144112,[Step02/08-BEFORE|DISTINATION],[FILE],/home/pi/data/python/temp/hoge/fuga/fileB.txt,8,2020-07-24 09:29:09.405717
20200725-144112,[Step02/08-BEFORE|DISTINATION],[FILE],/home/pi/data/python/temp/hoge/fuga/fileA.txt,8,2020-07-24 09:29:09.405717
20200725-144112,[Step03/08-DELETE|DISTINATION],[FILE],/home/pi/data/python/temp/hoge/fileB.txt
20200725-144112,[Step03/08-DELETE|DISTINATION],[FILE],/home/pi/data/python/temp/hoge/fileC.txt
20200725-144112,[Step03/08-DELETE|DISTINATION],[FILE],/home/pi/data/python/temp/hoge/fileA.txt
20200725-144112,[Step03/08-DELETE|DISTINATION],[NOT-DELETE],/home/pi/data/python/temp/hoge/fuga
20200725-144112,[Step04/08-DELETE-AFTER|DISTINATION],[DIRECTORY],/home/pi/data/python/temp/hoge/fuga
20200725-144112,[Step04/08-DELETE-AFTER|DISTINATION],[FILE],/home/pi/data/python/temp/hoge/fuga/fileB.txt,8,2020-07-24 09:29:09.405717
20200725-144112,[Step04/08-DELETE-AFTER|DISTINATION],[FILE],/home/pi/data/python/temp/hoge/fuga/fileA.txt,8,2020-07-24 09:29:09.405717
20200725-144112,[Step05/08-MOVE|DISTINATION],/home/pi/data/python/temp/hoge/fuga/fileB.txt,/home/pi/data/python/temp/hoge
20200725-144112,[Step05/08-MOVE|DISTINATION],/home/pi/data/python/temp/hoge/fuga/fileA.txt,/home/pi/data/python/temp/hoge
20200725-144112,[Step07/08-AFTER|DISTINATION],[FILE],/home/pi/data/python/temp/hoge/fileB.txt,8,2020-07-24 09:29:09.405717
20200725-144112,[Step07/08-AFTER|DISTINATION],[FILE],/home/pi/data/python/temp/hoge/fileA.txt,8,2020-07-24 09:29:09.405717
20200725-144112,[Step07/08-AFTER|DISTINATION],[DIRECTORY],/home/pi/data/python/temp/hoge/fuga
20200725-144112,[Step08/08-DELETE|SOURCE],/home/pi/data/python/temp/hoge/fuga
20200725-144112,SCRIPT-DONE
久しぶりにスクリプト書いて楽しかった。