1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

ファイルをごそっと移動するPython3スクリプト

Last updated at Posted at 2020-07-25

はじめに

  • 必要に迫られ、/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

line.png

久しぶりにスクリプト書いて楽しかった。

1
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?