Skip to content

Instantly share code, notes, and snippets.

@stuaxo
Last active April 18, 2024 22:13
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save stuaxo/f1beb981dc4845921c31fcb4e16f4821 to your computer and use it in GitHub Desktop.
Save stuaxo/f1beb981dc4845921c31fcb4e16f4821 to your computer and use it in GitHub Desktop.
List filenames and content ready for input to a LLM - optionally copy to the clipboard with a prompt.
#!/usr/bin/env python3
# Usage: python dirtogpt.py [--dir /path/to/directory] [--glob *.py] [--prompt [Custom prompt]] [--copy] [--exclude *.pyc]
import argparse
import pathlib
import fnmatch
try:
import pyperclip
except ImportError:
pyperclip = None
def append_file_content(output, path):
try:
content = path.read_text()
except UnicodeDecodeError:
#content = "Skipped (binary file)\n\n"
content = ""
except Exception as ex:
content = f"Skipped (error reading file: {ex})\n\n"
output += f"#:{path}:\n{content}\n\n"
return output
def dirtogpt(output, directory, glob, exclude):
file_count = 0
p = pathlib.Path(directory)
for child in p.iterdir():
if child.is_dir():
output, sub_file_count = dirtogpt(output, child, glob, exclude)
file_count += sub_file_count
for child in p.glob(glob):
if child.is_file() and not fnmatch.fnmatch(str(child), exclude):
output = append_file_content(output, child)
file_count += 1
return output, file_count
if __name__ == "__main__":
parser = argparse.ArgumentParser(description='Process some files.')
parser.add_argument('--dir', type=str, help='Directory to process', default=".")
parser.add_argument('--exclude', type=str, help='Glob pattern to exclude', default="")
parser.add_argument('--glob', type=str, help='Glob pattern to match', default="*")
parser.add_argument('--prompt', nargs='?', const="Filenames followed by file content-:", default=None, help='Display a prompt before the files')
parser.add_argument('--copy', action='store_true', help='Copy output to the clipboard instead of stdout')
args = parser.parse_args()
output = ""
if args.prompt is not None:
output += args.prompt + "\n"
output, file_count = dirtogpt(output, args.dir, args.glob, args.exclude)
token_count = len(output.split())
if args.copy:
if pyperclip:
pyperclip.copy(output)
print(f"Copied {file_count} files, {len(output)} bytes, and approximately {token_count} tokens to the clipboard.")
else:
print("The --copy option requires the 'pyperclip' module. Please install it to use this functionality.")
else:
print(output)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment