圧縮ファイルのテスト
圧縮ファイルをテストするときは、ファイルをサルベージしたときやHDDが壊れた、壊れそうなときなどでしょう。大抵そういうときはファイルが沢山有ります。
そういうときは
Pythonしか無いです。って事も無いかもしれませんが、少なくとも私はそうです。
でもコマンドプロンプト風に使いたい
ここからが本題です。外部コマンドを使用するときは、コマンドによって使い方が違います。この手のコマンドをそのまま文字列として渡せればきっと便利だろうと思って作りました。
import subprocess
import shutil
def command_check(chk: str) -> bool:
return False if shutil.which(chk) is None else True
def commands_check(*args) -> bool:
r = True
for i in args:
r = r and command_check(i)
return r
def make_command(cl: str) -> list:
r = []
s = ''
dqf = False
for i in cl:
if i == '"':
dqf = not dqf
elif i == ' ' and not dqf:
r += [s]
s = ''
else:
s += i
r += [s]
return r
def command_call(command, *args, disp=True, capture=False, **kwargs):
command = command if type(command) is list else make_command(command)
cl = []
for i in command:
f = False
for k,v in kwargs.items():
if i in '{'+k+'}':
f = True
cl += [i.format(**kwargs) if f else i]
ag = 0
for i in range(len(cl)):
if cl[i] == '[]':
cl[i] = args[ag]
ag += 1
if disp:
for i in cl:
print('"'+ i + '"' if ' ' in i else i, end=' ')
print()
return subprocess.run(cl, capture_output=capture, shell=True)
def main():
import glob,os,os.path,sys
cs = {
'.rar':['rar.exe','rar t []',2],
'.zip':['7za.exe','7za t []',10],
}
fld = 'f:\\temp'
if not commands_check(*[i[0] for i in cs.values()]):
print('コマンドが足りないです')
sys.exit()
fl = glob.glob(os.path.join(fld, '**/*.*'), recursive=True)
for i in fl:
ext = os.path.splitext(i)[1].lower()
if ext not in cs.keys():
continue
r = command_call(cs[ext][1], i, disp=True, capture=True).returncode
if r == cs[ext][2]:
print(i,' is broken')
os.rename(i,i+'.broken')
elif r != 0:
print(i,' is unknown')
os.rename(i, i+'.unknown')
if __name__ == '__main__':
main()
使い方(全体)
main
関数の下のcsに '.拡張子':['実行ファイル','コマンドライン',エラーコード],
を追加します。
ソースコード中では、7za.exe(7zip)とrar.exe(winrar)を使います。
コマンドライン中の[]
は任意のファイル名に置き換えられる部分です。
fld にチェックしたいディレクトリを記述して実行してください。
エラーコードと同じものがあればそのファイルに拡張子.brokenが追加されます。
使い方(関数)
command_check(chk: str) -> bool
strに実行したい外部コマンドを入れてこの関数を実行すると、そのコマンドが実行できればTrueが帰ってきます
例) command_check('rar')
def commands_check(*args) -> bool
command_checkの複数版です。一つでも無いものがある場合はFalseを返します。
例) `commands_check('rar','7za','ffmpeg')
def make_command(cl: str) -> list
一行に書かれたコマンドの書式をsubprocessで使用するリスト形式に直します。スペースで分割しますが、"で囲まれた部分は分割しません。コマンドプロンプトと同じ仕様です。
例) make_command('"C:\\Program Files\\hoge\\hoge.exe" -h aaa.dat')
def command_call(command, *args, disp=True, capture=False, **kwargs)
commandに書かれた外部コマンドを実行します。
command内では、[]
と{任意の文字}
が有るとそれぞれ*args , **kwargsに置換します。
command_call('xcopy [] []','C:\\','D:\\')
の場合
xcopy c:\ d:\のようになります。置換は出現順です。
command_call('xcopy {src} {dst}',src='C:\\',dst='E:\\')
のような記述も可能です。
disp Trueなら実行するコマンドを表示します。
capture Trueだと標準出力と標準エラー出力をキャプチャします、また、画面出力を行いません。
返値はsubprocess.runと同じです。
r = command_call......
r.returncode プロセスの返値
r.stdout (captureがTrueなら)標準出力
r.stderr (captureがTrueなら)標準エラー出力