306 lines
7.9 KiB
Python
306 lines
7.9 KiB
Python
import os
|
|
import time
|
|
import uuid
|
|
import rarfile
|
|
import zipfile
|
|
import shutil
|
|
import difflib
|
|
import subprocess
|
|
|
|
from pathlib import Path
|
|
|
|
|
|
m_dbgLevel = 0
|
|
listDbgStr = []
|
|
|
|
|
|
#
|
|
def IsEmptyStr(string):
|
|
return 0 == len(string.strip())
|
|
|
|
|
|
#
|
|
def GetCurrentTime():
|
|
# 현재 시간을 구하고 구조체로 변환
|
|
current_time_struct = time.localtime()
|
|
|
|
# 구조체에서 연, 월, 일, 시간, 분, 초를 추출
|
|
year = current_time_struct.tm_year
|
|
month = current_time_struct.tm_mon
|
|
day = current_time_struct.tm_mday
|
|
hour = current_time_struct.tm_hour
|
|
minute = current_time_struct.tm_min
|
|
second = current_time_struct.tm_sec
|
|
|
|
strRet = (f"{year}/{month}/{day}_{hour}:{minute}:{second}")
|
|
|
|
return strRet
|
|
|
|
|
|
#for debug
|
|
def DbgOut(strInput, bPrint = False):
|
|
strMsg = (f"{GetCurrentTime()} : {strInput}")
|
|
listDbgStr.append(strMsg)
|
|
|
|
if True == bPrint:
|
|
print(strMsg)
|
|
|
|
def printDbgMessages():
|
|
for line in listDbgStr:
|
|
print(line)
|
|
|
|
|
|
# 입력된 경로의 자식 폴더를 찾아 반환한다.
|
|
# 반환하는 리스트는 리커시브 - 손자, 증손자 폴더까지 전부 포함한다
|
|
def ListSubDirectories(root_dir):
|
|
subdirectories = []
|
|
|
|
# root_dir에서 하위 디렉토리 및 파일 목록을 얻음
|
|
for dirpath, dirnames, filenames in os.walk(root_dir):
|
|
# 하위 디렉토리 목록을 반복하며 하위 디렉토리만 추출
|
|
for dirname in dirnames:
|
|
path = os.path.join(dirpath, dirname)
|
|
|
|
if True == IsFinalFolder(path):
|
|
subdirectories.append(path)
|
|
|
|
return subdirectories
|
|
|
|
|
|
# 자식 폴더를 구해온다. 직계 자식만
|
|
def ListChildDirectories(pathDir):
|
|
listRet = []
|
|
for name in os.listdir(pathDir):
|
|
pathChild = os.path.join(pathDir, name)
|
|
if os.path.isdir(pathChild):
|
|
listRet.append(pathChild)
|
|
|
|
return listRet
|
|
|
|
|
|
# 파일목록만 구해온다. 자식 폴더에 있는건 무시.
|
|
def ListContainFiles(pathDir):
|
|
listRet = []
|
|
for name in os.listdir(pathDir):
|
|
pathChild = os.path.join(pathDir, name)
|
|
if not os.path.isdir(pathChild):
|
|
listRet.append(pathChild)
|
|
|
|
return listRet
|
|
|
|
|
|
def ListFileExtRcr(pathTrg, listExt):
|
|
listRet= []
|
|
|
|
if False == isinstance(listExt, list):
|
|
print("ext must list")
|
|
return
|
|
|
|
# pathTrg의 하위 디렉토리 및 파일 목록을 얻음
|
|
for dirpath, dirnames, filenames in os.walk(pathTrg):
|
|
for file in filenames:
|
|
extTmp = GetExtStr(file)
|
|
if extTmp.lower() in listExt and not file.startswith('.'):
|
|
listRet.append(os.path.join(dirpath, file))
|
|
|
|
return listRet
|
|
|
|
|
|
# 입력된 패스에서 부모 폴더를 찾는다. 0 은 자기자신 1은 부모, 숫자대로 위로.
|
|
def GetParentDirName(FullPath, nUp):
|
|
parts = FullPath.split(os.sep)
|
|
|
|
nTrgIdx = 0
|
|
if nUp < len(parts):
|
|
nTrgIdx = len(parts) -nUp -1
|
|
elif nUp < 0:
|
|
nTrgIdx = len(parts) - 1
|
|
else:
|
|
nTrgIdx = 0
|
|
|
|
return parts[nTrgIdx]
|
|
|
|
|
|
# 입력된 경로가 자식 폴더를 가지고 있는지 판단한다.- 최종 폴더인지 여부
|
|
# 자식이 없으면 True, 자식이 있으면 False
|
|
def IsFinalFolder(path):
|
|
bRet = True
|
|
|
|
contents = os.listdir(path)
|
|
for item in contents:
|
|
if True == os.path.isdir(item):
|
|
bRt = False
|
|
break
|
|
|
|
return bRet;
|
|
|
|
|
|
# 어떤 경로 안에서 특정 확장자의 파일을 뽑아내어 그 리스트를 반환한다.
|
|
def FindFileFromExt(path, ext):
|
|
bDot = False
|
|
if 0 <= ext.find('.'):
|
|
bDot = True
|
|
|
|
listRet = []
|
|
if False == os.path.exists(path):
|
|
return listRet
|
|
|
|
contents = os.listdir(path)
|
|
for item in contents:
|
|
if True == os.path.isdir(item):
|
|
continue
|
|
|
|
extItem = GetExtStr(item, bDot)
|
|
if extItem.lower() == ext.lower():
|
|
listRet.append(item)
|
|
|
|
return listRet
|
|
|
|
|
|
# 파일 이름에서 확장자를 뽑아낸다. True : '.' 을 포함한다.
|
|
def GetExtStr(file_path, bDot = True):
|
|
retStr = ""
|
|
# 파일 경로에서 마지막 점을 찾아 확장자를 추출
|
|
last_dot_index = file_path.rfind('.')
|
|
if last_dot_index == -1:
|
|
retStr = "" # 점이 없는 경우 확장자가 없음
|
|
else:
|
|
if True == bDot:
|
|
retStr = file_path[last_dot_index:]
|
|
else:
|
|
retStr = file_path[last_dot_index+1:]
|
|
|
|
return retStr
|
|
|
|
|
|
# 문자열에 포함된 단어를 지운다.
|
|
def RmvSubString(mainString, subString):
|
|
# 문자열에서 부분 문자열의 인덱스를 찾습니다.
|
|
strIdx = mainString.find(subString)
|
|
if strIdx == -1: # 부분 문자열이 존재하지 않으면 그대로 반환합니다.
|
|
return mainString
|
|
|
|
endIdx = strIdx + len(subString)
|
|
|
|
# 부분 문자열을 제거하고 새로운 문자열을 반환합니다.
|
|
return mainString[:strIdx] + mainString[endIdx:]
|
|
|
|
|
|
def ExtractZIP(zip_file, extract_to):
|
|
with zipfile.ZipFile(zip_file, 'r') as zf:
|
|
zf.extractall(extract_to)
|
|
|
|
|
|
#
|
|
def CreateZIP(output_zip, *files):
|
|
with zipfile.ZipFile(output_zip, 'w') as zf:
|
|
for file in files:
|
|
pathTemp = os.path.join('root', os.path.basename(file))
|
|
zf.write(file, pathTemp)
|
|
|
|
bRet = False
|
|
if os.path.exists(output_zip):
|
|
bRet = True
|
|
|
|
return bRet
|
|
|
|
# 파일 리스트에 들어있는 파일만 골라서 압축을 합니다. 상대경로를 제거하는게 기본값.
|
|
def CreateZIPShell(zipName, *files, bRmvRPath = True):
|
|
command = "zip "
|
|
|
|
if True == bRmvRPath:
|
|
command += "-j "
|
|
|
|
command += f"\"{zipName}\" "
|
|
|
|
# 이중 리스트인 이유를 모르겠다.
|
|
for file in files:
|
|
strTemp = ""
|
|
if isinstance(file, list):
|
|
strTemp = ' '.join(file)
|
|
else:
|
|
strTemp = f"\"{file}\" "
|
|
|
|
command += strTemp
|
|
|
|
# for item in file:
|
|
# command += f"\"{item}\" "
|
|
|
|
result = subprocess.run(command, shell=True, capture_output=True, text=True)
|
|
|
|
bRet = False
|
|
if 0 == result.returncode:
|
|
bRet = True
|
|
|
|
return bRet
|
|
|
|
|
|
# 특정 확장자만 쉘을 이용해서 압축한다
|
|
def CreateZIPShExt(zipName, TrgExt):
|
|
command = f"zip -j {zipName} *.{TrgExt}"
|
|
|
|
result = subprocess.run(command, shell=True, capture_output=True, text=True)
|
|
|
|
bRet = False
|
|
if 0 == result.returncode:
|
|
bRet = True
|
|
|
|
return bRet
|
|
|
|
|
|
# 압축 파일 내의 모든 파일 및 디렉토리 목록 가져오기
|
|
def GetZipContentList(path):
|
|
if None == path or not os.path.isfile(path):
|
|
return []
|
|
|
|
listRet = []
|
|
with zipfile.ZipFile( path , 'r') as zip_file:
|
|
listRet = zip_file.namelist()
|
|
|
|
return listRet
|
|
|
|
|
|
def GetZippedFileByte(pathZip, FileName):
|
|
if None == pathZip or not os.path.isfile(pathZip):
|
|
return None
|
|
|
|
retBytes = None
|
|
with zipfile.ZipFile( pathZip , 'r') as zip_file:
|
|
if not FileName in zip_file.namelist():
|
|
return None
|
|
|
|
with zip_file.open(FileName) as file:
|
|
retBytes = file.read()
|
|
|
|
return retBytes
|
|
|
|
|
|
# JSON 을 트리 구조로 출력한다.
|
|
def PrintJSONTree(data, indent=0):
|
|
if isinstance(data, dict):
|
|
for key, value in data.items():
|
|
print(' ' * indent + str(key))
|
|
PrintJSONTree(value, indent + 1)
|
|
elif isinstance(data, list):
|
|
for item in data:
|
|
PrintJSONTree(item, indent)
|
|
else:
|
|
print(' ' * indent + str(data))
|
|
|
|
|
|
def IsPathWithin(base_path: str, target_path: str) -> bool:
|
|
base = Path(base_path).resolve()
|
|
target = Path(target_path).resolve()
|
|
return target.is_relative_to(base)
|
|
|
|
|
|
# 랜덤 UUID 생성
|
|
def UUIDGenRandom():
|
|
random_uuid = uuid.uuid4()
|
|
return random_uuid
|
|
|
|
# 이름을 기반으로 UUID 생성
|
|
def UUIDGenName(SeedName):
|
|
namespace_uuid = uuid.uuid5(uuid.NAMESPACE_DNS, SeedName)
|
|
return namespace_uuid
|
|
|