Picking the right tools
Your entire script can be written as the following one-liner
grep -RiIl 'search' | xargs sed -i's/.*\(here\|there\|why\).*//g'
Whenever your entire script can be expressed as a oneliner, it is a good indication that something needs to change. The onliner is intentially obtuse, but I would argue your code is equally obtuse. You just do not know it, because you wrote it ;) I combined the ideas from here
https://www.internalpointers.com/post/linux-find-and-replace-text-multiple-files
with .*
to match anything zero or more times and then the list of banned words. Another solution from Overflow looks like this https://stackoverflow.com/questions/14443935/regex-search-replace-for-multiple-files-in-a-directory-using-python which is closer, but not quite where we want
Pythonic
What does pythonic mean? Does it mean "this code was written in Python"? No, see for instance Zen of Python.
Readability counts.
Take a step back. Breathe. Now look at your code. would you understand this code in a few hours, what about a few weeks, years? Your code is the first step to writing good code. Step 1, just make the freakin thing work.
A working code is like a book with a story but with no commas sections paragraphs commas or periods and it is just a big blob of text while the whole story is in there and every part makes sense to the author but it can be a big challenging for another person or your future self to read it dont you agree
Pythons chapters is files. Our table of contents is the docstring of each file. Then we put our code into paragraphs or functions, and explain the purpose of each paragraph. This is done by clear variable names, doctests and docstrings and typing hints.
Improvements
Today we try to prefer to use the pathlib
library to handle paths instead of os
. (I know many still prefer walk), but learning to use the pathlib is never a bad idea.
Explicit is better than implicit. You need to name "to-remove" better. 1) It needs a filetype to be specific. 2) You need to inform that this is a "user created file".
user_words_to_remove.txt
Notice how we used underscores as this is prefered by python. 3) This should really be a global constant, or even better prompted using sys.args
or even better argparse
(click is overkill)
Learn to use early exits. This
if any([ignore_file in current_file for ignore_file in ignore_files]):
pass
else:
with open(current_file, "r") as in_file:
in_file_lines = in_file.readlines()
print("IN FILE:")
print(in_file_lines)
is better formated as
if any([ignore_file in current_file for ignore_file in ignore_files]):
continue
with open(current_file, "r") as in_file:
in_file_lines = in_file.readlines()
print("IN FILE:")
print(in_file_lines)
Do not print everywhere! Separate business logic from the UI. Have functions that have a sole purpose of printing, and one that has a sole purpose of fetching files.
something like the below would be a start
from pathlib import Path
def walk(path:Path, recursive:bool=False, depth:int=0) -> Path:
if depth > 0 and not recursive:
return
for p in Path(path).iterdir():
if p.is_dir():
yield from walk(p, depth=depth+1)
continue
yield p.resolve()
def legal_files(directory:Path|str=Path.cwd(), files_2_exclude:list[str]) -> Path:
for f in walk(Path(directory)):
if f.name not in files_2_exclude:
yield f
Note how no file directory will ever hit the recursion limit so using recursion here is fine.. Now we can simply iterate over the legal files.
From here I would compile some regex, and possibly do something like below
import re
WORDS_2_EXCLUDE = ["sit", "lorem", "lipsum"]
REPLACE_LINES = re.compile(r"^.*("+"|".join(WORDS_2_EXCLUDE)+").*$")
def replace_files_in_path(path, recursive:bool=False) -> None:
for filepath in legal_files(path, recursive=recursive):
with open(filepath, "r") as f:
new_content = REPLACE_LINES.sub("", f.read())
with open(filepath, "w") as f:
f.write(new_content)
Note that the code above is not tested, it will have bugs. The best way to learn is to fix those bugs, and understand the code. I would also to recommend implementing the recursive
option so your users can choose to iterate recursively, or just search the current directory. I gave it an attempt, but make sure it actually works.
Good luck improving!
to-remove
file. \$\endgroup\$