forked from CarletonArchives/BagBatch
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathbagbatch.py
212 lines (189 loc) · 7.42 KB
/
bagbatch.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
"""
bagbatch.py
Written to run BagIt on multiple directories at once.
BagBatch Version 1.1.5
Updated August 29, 2017
Usage: python bagbatch.py <command> <dir>
<command> is the command used on the directory's subdirectories.
If no command is specified, 'baginplace' is used.
<dir> is the parent of the subdirectories to run the command on
If no directory is specified, program will prompt for one.
BAGIT_INST_PATH.txt will contain the installation path to bag.bat
Input: Parent directory with subdirectories to bag, verifyvalid, or
update.
Output: Parent directory with bagged subdirectories.
Dependency: BAGIT_INST_PATH.txt
The first time bagbatch.py is run, it will create BAGIT_INST_PATH.txt
and prompt for the path of the BagIt installation. Within this folder,
there will be a folder named 'bin' containing bag.bat. This
path will most likely be "C:\Program Files\bagit-X.X.X".
The path will be saved in BAGIT_INST_PATH.txt. Each time bagbatch.py is run, it will validate this location.
"""
import os, sys, platform, datetime
import shlex, subprocess
import tkinter
from tkinter import filedialog
VERSION = '1.1.5'
BAGIT_INST_PATH = "BAGIT_INST_PATH.txt"
BAGBATCH_DIR = os.getcwd()
today = datetime.datetime.now()
LOGLOCATION = "BagBatchLogLocale.txt"
LOGFILE = "BagBatchLog-"+today.strftime("%m-%d-%y_%H-%M-%S")+".txt"
def call_bag_command(directory, command):
""" Given a single directory, calls bag <command> <dir> using
subprocess.check_call() for Windows. Errors will be printed out. """
print ('----------------------\n',command + ':', os.path.normpath(directory) + ".")
with open(BAGIT_INST_PATH) as bb_path:
path = bb_path.read()
os.chdir(path)
try:
if get_ext() == '.bat':
subprocess.check_call([os.path.join(path, 'bag'), command, directory], shell=True)
return True
else:
print ('Error detecting Windows')
return False
except:
print ("Error:", command, "was not successful. Look in the readme for troubleshooting.")
return False
def get_immediate_subdirectories(directory):
""" Given a directory name, finds all immediate subdirectories and returns
the complete directory paths in a list. source:
http://stackoverflow.com/a/800201 """
dirNames = [name for name in os.listdir(directory)
if os.path.isdir(os.path.join(directory, name))]
dirList = []
for d in dirNames:
dirList.append(os.path.join(directory,d))
return dirList
def validate_bagit_path():
""" Validates the path to BagIt installation folder containing bin/bag.bat. Prompts for a new path and resets old path if needed. """
print ("\nValidating BagIt installation path...")
# Creates the text file with the bagit path, if need be
if not os.path.isfile(BAGIT_INST_PATH):
bb_file = open(BAGIT_INST_PATH, "w")
bb_file.close()
# closes file after with statement
with open(BAGIT_INST_PATH, "r+") as bb_path:
path = bb_path.read()
# if the path exists and the files are present, return and start bagging
path = os.path.normpath(path)
if path and os.path.exists(path) and not path == '':
if not 'bin' in path:
path = os.path.join(path,'bin')
if os.path.isfile(os.path.join(path,'bag')):
print ("Validated.\n")
return
else:
print ('cannot find extension')
# if not, prompt for new path, write to BAGIT_INST_PATH.txt, and validate
message = '\nSelect the BagIt installation folder. This folder may be located in Program Files (Windows). This will resemble bagit-X.X.X where \'X.X.X\' is the version number.'
path = select_folder(message)
# if there are extra quoting characters, remove them
if '"' in path or "'" in path:
path=''.join(shlex.split(path))
try:
path_bin = path + '/bin'
if not os.path.isfile(path_bin):
print ('not a valid folder')
except:
print ('no bin path')
bb_file = open(BAGIT_INST_PATH, "w")
bb_file.write(path_bin.strip())
bb_file.close()
validate_bagit_path()
def select_folder(message):
print (message)
root = tkinter.Tk()
root.withdraw()
result = filedialog.askdirectory(parent = root, title = message)
if not result:
print ('\nExiting bagbatch.py')
sys.exit()
return result
def get_ext():
""" Based on the operation system, returns the correct file extension for. """
if 'Windows' in platform.system() or 'win32' == sys.platform:
return '.bat'
else:
print ('\nExiting bagbatch.py')
sys.exit()
def validate_logfile_path():
""" Validates the path to the folder for logs. Prompts for new selection if needed"""
print ("\nValidating Folder for logs")
# Creates the text file with the logfile path, if need be
if not os.path.isfile(LOGLOCATION):
ll_file = open(LOGLOCATION, "w")
ll_file.close()
# closes file after with statement
with open(LOGLOCATION, "r+") as ll_path:
path = ll_path.read()
# if the path exists, return and start bagging
path = os.path.normpath(path)
if path and os.path.exists(path) and not path == '':
print (path)
print ("Validated.\n")
return
else:
# if not, prompt for new path, write to BagBatchLogLocale.txt, and validate
message = '\nSelect a folder for logfiles from bagbatch to go'
path = select_folder(message)
# if there are extra quoting characters, remove them
if '"' in path or "'" in path:
path=''.join(shlex.split(path))
ll_file = open(LOGLOCATION, "w")
ll_file.write(path.strip())
ll_file.close()
validate_logfile_path()
def valid_commands():
return {'baginplace':'Creates a bag-in-place. The source must be a directory on a filesystem and may already have a data directory.',
'update':'Updates the manifests and (if it exists) the bag-info.txt for a bag.',
'verifyvalid':'Verifies the validity of a bag.'}
def usage_message():
print ("BagBatch Version",VERSION)
print ("Usage:\tpython bagbatch.py <command>")
print ("\tOr:\tpython bagbatch.py <command> <dir>")
print ("\t\t<dir> is the parent dir of the subdirectories")
print ("\tBAGIT_INST_PATH.txt will contain the installation path: bagit-X.X.X")
print ("Valid Commands:")
for cmd in valid_commands():
print ('\t' + cmd + ': \t' + valid_commands()[cmd])
def main():
command = 'baginplace'
if len(sys.argv) == 1:
return usage_message()
if len(sys.argv) == 2:
if sys.argv[1] == 'help' or sys.argv[1] == 'version':
return usage_message()
elif not sys.argv[1] in valid_commands():
print ("\nInvalid command given. Using",command,"instead.")
elif sys.argv[1] in valid_commands():
command = sys.argv[1]
if os.path.exists(sys.argv[1]):
dirToBag = sys.argv[1]
else:
dirToBag = select_folder('Select the parent folder containing the folders to %s.' %command)
elif len(sys.argv) == 3:
if sys.argv[1] in valid_commands():
command = sys.argv[1]
if os.path.exists(sys.argv[2]):
dirToBag = sys.argv[2]
else:
print ("\nInvalid folder path. Please select the correct folder.")
dirToBag = select_folder('Select the parent folder containing the folders to %s.' %command)
validate_bagit_path()
validate_logfile_path()
dirToBag = os.path.normpath(dirToBag)
print ("----------------------\nRunning",command,"for all directories in",)
print (dirToBag + ".\n----------------------")
success = True
for d in get_immediate_subdirectories(dirToBag):
# calls 'bag <dir> <command>' for each directory
if not call_bag_command(d, command):
success = False
os.chdir(BAGBATCH_DIR)
if success:
print ("\n----------------------\n----------------------\nBags Complete.\n----------------------")
else:
print ("----------------------\n----------------------\nBags not complete: Error with bags.\n----------------------")
main()