Directory Clean Up
Clash Royale CLAN TAG#URR8PPP
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty margin-bottom:0;
up vote
4
down vote
favorite
I am brand new to Python coming from Ruby on Rails. I am building a cleanup script for cleaning (archiving, deleting, or viewing) directories. I would love to know anything that I can make better, safer, faster.
import os
import re
import shutil
import argparse
from datetime import datetime
# Example: python cleanup.py -d u:jobs -p u:jobspattern_file.txt -r list
"""
Example pattern file:
template
^d5,
twin
"""
parser = argparse.ArgumentParser()
parser.add_argument('-p', type=str, default="pattern_file.txt", help="Pattern File (One item per line, regex or string)")
parser.add_argument('-d', help='Directory to clean up.')
parser.add_argument('-a', help='Minimum number of days old to clean up.')
parser.add_argument('-r', type=str, help='delete, archive or test.')
args = parser.parse_args()
def included_files(directory, pattern_file, age_string = 90):
""" Find files to move """
all_files =
excluded_files =
os.chdir(directory)
patterns = fix_pattern(pattern_file)
for fname in os.listdir(directory):
all_files.append(fname)
for pattern in patterns:
# Check for matching pattern in filename
if re.search(pattern, fname.lower()): # Regex search
excluded_files.append(fname)
# Check to see if the difference in today and modified date is more than "age"
now = datetime.now()
then = datetime.fromtimestamp(os.path.getmtime(fname))
tdelta = now - then
if type(age_string) == str:
age = int(age_string)
else:
age = 90
if tdelta.days < age:
excluded_files.append(fname)
value = [x for x in all_files if x not in excluded_files]
return value
def file_maintenance(dir_path, files, type):
""" File Maintenance """
if os.path.isdir(dir_path):
directory = dir_path
else:
directory = os.path.dirname(os.path.realpath(__file__))
archive_directory = os.path.join(directory.strip(), 'archive', "")
for file in files:
if os.path.isdir(file) is not True:
if type is "archive":
if os.path.isdir(archive_directory) is not True:
os.makedirs(archive_directory)
print("Moving " + os.path.join(directory, file) + " to " + os.path.join(archive_directory, file))
shutil.move(os.path.join(directory, file), os.path.join(archive_directory, file))
elif type is "delete":
print('Deleting ' + os.path.join(directory, file))
os.remove(file)
else:
print("File: " + os.path.join(directory, file))
def fix_pattern(pattern_file):
if os.path.isfile(pattern_file):
print("pattern file found")
with open(pattern_file) as f:
content = f.readlines()
pattern = [x.strip() for x in content]
else:
print("pattern file not found")
pattern =
pattern.append('pattern_file')
return pattern
if __name__ == "__main__":
files = included_files(args.d, args.p, args.a)
file_maintenance(args.d, files, args.r)
python
add a comment |Â
up vote
4
down vote
favorite
I am brand new to Python coming from Ruby on Rails. I am building a cleanup script for cleaning (archiving, deleting, or viewing) directories. I would love to know anything that I can make better, safer, faster.
import os
import re
import shutil
import argparse
from datetime import datetime
# Example: python cleanup.py -d u:jobs -p u:jobspattern_file.txt -r list
"""
Example pattern file:
template
^d5,
twin
"""
parser = argparse.ArgumentParser()
parser.add_argument('-p', type=str, default="pattern_file.txt", help="Pattern File (One item per line, regex or string)")
parser.add_argument('-d', help='Directory to clean up.')
parser.add_argument('-a', help='Minimum number of days old to clean up.')
parser.add_argument('-r', type=str, help='delete, archive or test.')
args = parser.parse_args()
def included_files(directory, pattern_file, age_string = 90):
""" Find files to move """
all_files =
excluded_files =
os.chdir(directory)
patterns = fix_pattern(pattern_file)
for fname in os.listdir(directory):
all_files.append(fname)
for pattern in patterns:
# Check for matching pattern in filename
if re.search(pattern, fname.lower()): # Regex search
excluded_files.append(fname)
# Check to see if the difference in today and modified date is more than "age"
now = datetime.now()
then = datetime.fromtimestamp(os.path.getmtime(fname))
tdelta = now - then
if type(age_string) == str:
age = int(age_string)
else:
age = 90
if tdelta.days < age:
excluded_files.append(fname)
value = [x for x in all_files if x not in excluded_files]
return value
def file_maintenance(dir_path, files, type):
""" File Maintenance """
if os.path.isdir(dir_path):
directory = dir_path
else:
directory = os.path.dirname(os.path.realpath(__file__))
archive_directory = os.path.join(directory.strip(), 'archive', "")
for file in files:
if os.path.isdir(file) is not True:
if type is "archive":
if os.path.isdir(archive_directory) is not True:
os.makedirs(archive_directory)
print("Moving " + os.path.join(directory, file) + " to " + os.path.join(archive_directory, file))
shutil.move(os.path.join(directory, file), os.path.join(archive_directory, file))
elif type is "delete":
print('Deleting ' + os.path.join(directory, file))
os.remove(file)
else:
print("File: " + os.path.join(directory, file))
def fix_pattern(pattern_file):
if os.path.isfile(pattern_file):
print("pattern file found")
with open(pattern_file) as f:
content = f.readlines()
pattern = [x.strip() for x in content]
else:
print("pattern file not found")
pattern =
pattern.append('pattern_file')
return pattern
if __name__ == "__main__":
files = included_files(args.d, args.p, args.a)
file_maintenance(args.d, files, args.r)
python
add a comment |Â
up vote
4
down vote
favorite
up vote
4
down vote
favorite
I am brand new to Python coming from Ruby on Rails. I am building a cleanup script for cleaning (archiving, deleting, or viewing) directories. I would love to know anything that I can make better, safer, faster.
import os
import re
import shutil
import argparse
from datetime import datetime
# Example: python cleanup.py -d u:jobs -p u:jobspattern_file.txt -r list
"""
Example pattern file:
template
^d5,
twin
"""
parser = argparse.ArgumentParser()
parser.add_argument('-p', type=str, default="pattern_file.txt", help="Pattern File (One item per line, regex or string)")
parser.add_argument('-d', help='Directory to clean up.')
parser.add_argument('-a', help='Minimum number of days old to clean up.')
parser.add_argument('-r', type=str, help='delete, archive or test.')
args = parser.parse_args()
def included_files(directory, pattern_file, age_string = 90):
""" Find files to move """
all_files =
excluded_files =
os.chdir(directory)
patterns = fix_pattern(pattern_file)
for fname in os.listdir(directory):
all_files.append(fname)
for pattern in patterns:
# Check for matching pattern in filename
if re.search(pattern, fname.lower()): # Regex search
excluded_files.append(fname)
# Check to see if the difference in today and modified date is more than "age"
now = datetime.now()
then = datetime.fromtimestamp(os.path.getmtime(fname))
tdelta = now - then
if type(age_string) == str:
age = int(age_string)
else:
age = 90
if tdelta.days < age:
excluded_files.append(fname)
value = [x for x in all_files if x not in excluded_files]
return value
def file_maintenance(dir_path, files, type):
""" File Maintenance """
if os.path.isdir(dir_path):
directory = dir_path
else:
directory = os.path.dirname(os.path.realpath(__file__))
archive_directory = os.path.join(directory.strip(), 'archive', "")
for file in files:
if os.path.isdir(file) is not True:
if type is "archive":
if os.path.isdir(archive_directory) is not True:
os.makedirs(archive_directory)
print("Moving " + os.path.join(directory, file) + " to " + os.path.join(archive_directory, file))
shutil.move(os.path.join(directory, file), os.path.join(archive_directory, file))
elif type is "delete":
print('Deleting ' + os.path.join(directory, file))
os.remove(file)
else:
print("File: " + os.path.join(directory, file))
def fix_pattern(pattern_file):
if os.path.isfile(pattern_file):
print("pattern file found")
with open(pattern_file) as f:
content = f.readlines()
pattern = [x.strip() for x in content]
else:
print("pattern file not found")
pattern =
pattern.append('pattern_file')
return pattern
if __name__ == "__main__":
files = included_files(args.d, args.p, args.a)
file_maintenance(args.d, files, args.r)
python
I am brand new to Python coming from Ruby on Rails. I am building a cleanup script for cleaning (archiving, deleting, or viewing) directories. I would love to know anything that I can make better, safer, faster.
import os
import re
import shutil
import argparse
from datetime import datetime
# Example: python cleanup.py -d u:jobs -p u:jobspattern_file.txt -r list
"""
Example pattern file:
template
^d5,
twin
"""
parser = argparse.ArgumentParser()
parser.add_argument('-p', type=str, default="pattern_file.txt", help="Pattern File (One item per line, regex or string)")
parser.add_argument('-d', help='Directory to clean up.')
parser.add_argument('-a', help='Minimum number of days old to clean up.')
parser.add_argument('-r', type=str, help='delete, archive or test.')
args = parser.parse_args()
def included_files(directory, pattern_file, age_string = 90):
""" Find files to move """
all_files =
excluded_files =
os.chdir(directory)
patterns = fix_pattern(pattern_file)
for fname in os.listdir(directory):
all_files.append(fname)
for pattern in patterns:
# Check for matching pattern in filename
if re.search(pattern, fname.lower()): # Regex search
excluded_files.append(fname)
# Check to see if the difference in today and modified date is more than "age"
now = datetime.now()
then = datetime.fromtimestamp(os.path.getmtime(fname))
tdelta = now - then
if type(age_string) == str:
age = int(age_string)
else:
age = 90
if tdelta.days < age:
excluded_files.append(fname)
value = [x for x in all_files if x not in excluded_files]
return value
def file_maintenance(dir_path, files, type):
""" File Maintenance """
if os.path.isdir(dir_path):
directory = dir_path
else:
directory = os.path.dirname(os.path.realpath(__file__))
archive_directory = os.path.join(directory.strip(), 'archive', "")
for file in files:
if os.path.isdir(file) is not True:
if type is "archive":
if os.path.isdir(archive_directory) is not True:
os.makedirs(archive_directory)
print("Moving " + os.path.join(directory, file) + " to " + os.path.join(archive_directory, file))
shutil.move(os.path.join(directory, file), os.path.join(archive_directory, file))
elif type is "delete":
print('Deleting ' + os.path.join(directory, file))
os.remove(file)
else:
print("File: " + os.path.join(directory, file))
def fix_pattern(pattern_file):
if os.path.isfile(pattern_file):
print("pattern file found")
with open(pattern_file) as f:
content = f.readlines()
pattern = [x.strip() for x in content]
else:
print("pattern file not found")
pattern =
pattern.append('pattern_file')
return pattern
if __name__ == "__main__":
files = included_files(args.d, args.p, args.a)
file_maintenance(args.d, files, args.r)
python
edited Apr 5 at 21:41
asked Apr 5 at 20:04
Toby Joiner
1235
1235
add a comment |Â
add a comment |Â
1 Answer
1
active
oldest
votes
up vote
3
down vote
accepted
I would do the following:
- Use PyCharm or IntelliJ IDEA with the Python plugin. Either will detect several of the following issues, and you can simply cycle through them using F2.
- Put the argument parsing inside a function. It's clearer and you avoid issues with importing your stuff from other code.
- Run the code through
pycodestyle
to discover several issues such asfoo is not True
which should benot foo
. - Use long name options such as
--pattern-file
to make your options obvious to a new user. - Always treat
age_string
as anint
. This means setting the ArgumentParser argument type, renaming the parameter and removing all theif type(age_string) == str
stuff. - Inline the
value
variable - it's only used once, and that in a trivial manner. - Use a single list rather than adding all the files to a list, then creating a list of exclusions, then subtracting one from the other. Do all the checks and
continue
the loop if any of them apply to the file under consideration. - Create constants for any magic values, for example
archive
and90
. - Understand why the string
pattern_file
is added to the pattern list, and most likely remove it. - Make it obvious (in the code, not just the argument help text) that the patterns are lists of exclusions.
- In general, don't try to second guess the user's intentions. For example, it should be an error if you have a
dir_path
parameter which does not point to an existing directory. If it points to a file then the user has misunderstood how to use it.
1
While I agree with most of your points, I think relying on an IDE to find and fix errors for you isn't going to help you improve your coding skills as a whole.
â Daniel
Apr 6 at 6:51
I think you might have misread my answer, as "relying on" is nowhere to be found in it.
â l0b0
Apr 6 at 7:53
2
As I don't feel like creating a new answer for such minor points, two additions related toargparse
that you could mention: usedefault=90
for the-a
option and usechoices=...
(or a subcommand) for the-r
option.
â Mathias Ettinger
Apr 6 at 15:00
Thank you for the comments and ideas. This is the first time I have found code review, so also thanks for the great first experience!
â Toby Joiner
Apr 6 at 16:59
add a comment |Â
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
3
down vote
accepted
I would do the following:
- Use PyCharm or IntelliJ IDEA with the Python plugin. Either will detect several of the following issues, and you can simply cycle through them using F2.
- Put the argument parsing inside a function. It's clearer and you avoid issues with importing your stuff from other code.
- Run the code through
pycodestyle
to discover several issues such asfoo is not True
which should benot foo
. - Use long name options such as
--pattern-file
to make your options obvious to a new user. - Always treat
age_string
as anint
. This means setting the ArgumentParser argument type, renaming the parameter and removing all theif type(age_string) == str
stuff. - Inline the
value
variable - it's only used once, and that in a trivial manner. - Use a single list rather than adding all the files to a list, then creating a list of exclusions, then subtracting one from the other. Do all the checks and
continue
the loop if any of them apply to the file under consideration. - Create constants for any magic values, for example
archive
and90
. - Understand why the string
pattern_file
is added to the pattern list, and most likely remove it. - Make it obvious (in the code, not just the argument help text) that the patterns are lists of exclusions.
- In general, don't try to second guess the user's intentions. For example, it should be an error if you have a
dir_path
parameter which does not point to an existing directory. If it points to a file then the user has misunderstood how to use it.
1
While I agree with most of your points, I think relying on an IDE to find and fix errors for you isn't going to help you improve your coding skills as a whole.
â Daniel
Apr 6 at 6:51
I think you might have misread my answer, as "relying on" is nowhere to be found in it.
â l0b0
Apr 6 at 7:53
2
As I don't feel like creating a new answer for such minor points, two additions related toargparse
that you could mention: usedefault=90
for the-a
option and usechoices=...
(or a subcommand) for the-r
option.
â Mathias Ettinger
Apr 6 at 15:00
Thank you for the comments and ideas. This is the first time I have found code review, so also thanks for the great first experience!
â Toby Joiner
Apr 6 at 16:59
add a comment |Â
up vote
3
down vote
accepted
I would do the following:
- Use PyCharm or IntelliJ IDEA with the Python plugin. Either will detect several of the following issues, and you can simply cycle through them using F2.
- Put the argument parsing inside a function. It's clearer and you avoid issues with importing your stuff from other code.
- Run the code through
pycodestyle
to discover several issues such asfoo is not True
which should benot foo
. - Use long name options such as
--pattern-file
to make your options obvious to a new user. - Always treat
age_string
as anint
. This means setting the ArgumentParser argument type, renaming the parameter and removing all theif type(age_string) == str
stuff. - Inline the
value
variable - it's only used once, and that in a trivial manner. - Use a single list rather than adding all the files to a list, then creating a list of exclusions, then subtracting one from the other. Do all the checks and
continue
the loop if any of them apply to the file under consideration. - Create constants for any magic values, for example
archive
and90
. - Understand why the string
pattern_file
is added to the pattern list, and most likely remove it. - Make it obvious (in the code, not just the argument help text) that the patterns are lists of exclusions.
- In general, don't try to second guess the user's intentions. For example, it should be an error if you have a
dir_path
parameter which does not point to an existing directory. If it points to a file then the user has misunderstood how to use it.
1
While I agree with most of your points, I think relying on an IDE to find and fix errors for you isn't going to help you improve your coding skills as a whole.
â Daniel
Apr 6 at 6:51
I think you might have misread my answer, as "relying on" is nowhere to be found in it.
â l0b0
Apr 6 at 7:53
2
As I don't feel like creating a new answer for such minor points, two additions related toargparse
that you could mention: usedefault=90
for the-a
option and usechoices=...
(or a subcommand) for the-r
option.
â Mathias Ettinger
Apr 6 at 15:00
Thank you for the comments and ideas. This is the first time I have found code review, so also thanks for the great first experience!
â Toby Joiner
Apr 6 at 16:59
add a comment |Â
up vote
3
down vote
accepted
up vote
3
down vote
accepted
I would do the following:
- Use PyCharm or IntelliJ IDEA with the Python plugin. Either will detect several of the following issues, and you can simply cycle through them using F2.
- Put the argument parsing inside a function. It's clearer and you avoid issues with importing your stuff from other code.
- Run the code through
pycodestyle
to discover several issues such asfoo is not True
which should benot foo
. - Use long name options such as
--pattern-file
to make your options obvious to a new user. - Always treat
age_string
as anint
. This means setting the ArgumentParser argument type, renaming the parameter and removing all theif type(age_string) == str
stuff. - Inline the
value
variable - it's only used once, and that in a trivial manner. - Use a single list rather than adding all the files to a list, then creating a list of exclusions, then subtracting one from the other. Do all the checks and
continue
the loop if any of them apply to the file under consideration. - Create constants for any magic values, for example
archive
and90
. - Understand why the string
pattern_file
is added to the pattern list, and most likely remove it. - Make it obvious (in the code, not just the argument help text) that the patterns are lists of exclusions.
- In general, don't try to second guess the user's intentions. For example, it should be an error if you have a
dir_path
parameter which does not point to an existing directory. If it points to a file then the user has misunderstood how to use it.
I would do the following:
- Use PyCharm or IntelliJ IDEA with the Python plugin. Either will detect several of the following issues, and you can simply cycle through them using F2.
- Put the argument parsing inside a function. It's clearer and you avoid issues with importing your stuff from other code.
- Run the code through
pycodestyle
to discover several issues such asfoo is not True
which should benot foo
. - Use long name options such as
--pattern-file
to make your options obvious to a new user. - Always treat
age_string
as anint
. This means setting the ArgumentParser argument type, renaming the parameter and removing all theif type(age_string) == str
stuff. - Inline the
value
variable - it's only used once, and that in a trivial manner. - Use a single list rather than adding all the files to a list, then creating a list of exclusions, then subtracting one from the other. Do all the checks and
continue
the loop if any of them apply to the file under consideration. - Create constants for any magic values, for example
archive
and90
. - Understand why the string
pattern_file
is added to the pattern list, and most likely remove it. - Make it obvious (in the code, not just the argument help text) that the patterns are lists of exclusions.
- In general, don't try to second guess the user's intentions. For example, it should be an error if you have a
dir_path
parameter which does not point to an existing directory. If it points to a file then the user has misunderstood how to use it.
edited Apr 6 at 0:00
answered Apr 5 at 23:18
l0b0
3,580922
3,580922
1
While I agree with most of your points, I think relying on an IDE to find and fix errors for you isn't going to help you improve your coding skills as a whole.
â Daniel
Apr 6 at 6:51
I think you might have misread my answer, as "relying on" is nowhere to be found in it.
â l0b0
Apr 6 at 7:53
2
As I don't feel like creating a new answer for such minor points, two additions related toargparse
that you could mention: usedefault=90
for the-a
option and usechoices=...
(or a subcommand) for the-r
option.
â Mathias Ettinger
Apr 6 at 15:00
Thank you for the comments and ideas. This is the first time I have found code review, so also thanks for the great first experience!
â Toby Joiner
Apr 6 at 16:59
add a comment |Â
1
While I agree with most of your points, I think relying on an IDE to find and fix errors for you isn't going to help you improve your coding skills as a whole.
â Daniel
Apr 6 at 6:51
I think you might have misread my answer, as "relying on" is nowhere to be found in it.
â l0b0
Apr 6 at 7:53
2
As I don't feel like creating a new answer for such minor points, two additions related toargparse
that you could mention: usedefault=90
for the-a
option and usechoices=...
(or a subcommand) for the-r
option.
â Mathias Ettinger
Apr 6 at 15:00
Thank you for the comments and ideas. This is the first time I have found code review, so also thanks for the great first experience!
â Toby Joiner
Apr 6 at 16:59
1
1
While I agree with most of your points, I think relying on an IDE to find and fix errors for you isn't going to help you improve your coding skills as a whole.
â Daniel
Apr 6 at 6:51
While I agree with most of your points, I think relying on an IDE to find and fix errors for you isn't going to help you improve your coding skills as a whole.
â Daniel
Apr 6 at 6:51
I think you might have misread my answer, as "relying on" is nowhere to be found in it.
â l0b0
Apr 6 at 7:53
I think you might have misread my answer, as "relying on" is nowhere to be found in it.
â l0b0
Apr 6 at 7:53
2
2
As I don't feel like creating a new answer for such minor points, two additions related to
argparse
that you could mention: use default=90
for the -a
option and use choices=...
(or a subcommand) for the -r
option.â Mathias Ettinger
Apr 6 at 15:00
As I don't feel like creating a new answer for such minor points, two additions related to
argparse
that you could mention: use default=90
for the -a
option and use choices=...
(or a subcommand) for the -r
option.â Mathias Ettinger
Apr 6 at 15:00
Thank you for the comments and ideas. This is the first time I have found code review, so also thanks for the great first experience!
â Toby Joiner
Apr 6 at 16:59
Thank you for the comments and ideas. This is the first time I have found code review, so also thanks for the great first experience!
â Toby Joiner
Apr 6 at 16:59
add a comment |Â
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f191352%2fdirectory-clean-up%23new-answer', 'question_page');
);
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password