Skip to content

Commit

Permalink
feat: add find files and folder function
Browse files Browse the repository at this point in the history
  • Loading branch information
aboutmydreams committed May 20, 2024
1 parent 7f12111 commit b4f8e14
Show file tree
Hide file tree
Showing 6 changed files with 215 additions and 10 deletions.
61 changes: 61 additions & 0 deletions tests/test_tree.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import os
import shutil
import unittest
from io import StringIO
from unittest.mock import patch
from way3 import tree


class TestTreeFunction(unittest.TestCase):
@classmethod
def setUpClass(cls):
os.makedirs("test_dir/sub_dir1")
os.makedirs("test_dir/sub_dir2")
with open("test_dir/file1.txt", "w") as f:
f.write("file1")
with open("test_dir/file2.txt", "w") as f:
f.write("file2")
with open("test_dir/sub_dir1/file3.txt", "w") as f:
f.write("file3")

@classmethod
def tearDownClass(cls):
shutil.rmtree("test_dir")

@patch("sys.stdout", new_callable=StringIO)
def test_tree_basic(self, mock_stdout):
tree("test_dir")
output = mock_stdout.getvalue().strip()
expected_output = "\n".join(
[
"|-- file1.txt",
"|-- file2.txt",
"|-- sub_dir1",
"| |-- file3.txt",
"|-- sub_dir2",
]
)
self.assertEqual(output, expected_output)

@patch("sys.stdout", new_callable=StringIO)
def test_tree_full_path(self, mock_stdout):
tree("test_dir", full_path=True)
output = mock_stdout.getvalue().strip()
expected_output = "\n".join(
[
f"|-- {os.path.join('test_dir', 'file1.txt')}",
f"|-- {os.path.join('test_dir', 'file2.txt')}",
f"|-- {os.path.join('test_dir', 'sub_dir1')}",
f"| |-- {os.path.join('test_dir', 'sub_dir1', 'file3.txt')}",
f"|-- {os.path.join('test_dir', 'sub_dir2')}",
]
)
self.assertEqual(output, expected_output)

@patch("sys.stdout", new_callable=StringIO)
def test_tree_show_permissions(self, mock_stdout):
tree("test_dir", show_permissions=True)
output = mock_stdout.getvalue().strip()
self.assertIn("|-- ", output)
self.assertIn(" file1.txt", output)
self.assertIn(" sub_dir1", output)
17 changes: 11 additions & 6 deletions way3/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,20 +13,22 @@

# File Find
from .file_find.current_dir import get_current_dir as get_current_dir # noqa: E402
from .file_find.traverse_files_from_folder import parse_gitignore as parse_gitignore # noqa: E402
from .file_find.traverse_files_from_folder import is_gitignored as is_gitignored # noqa: E402
from .file_find.traverse_files_from_folder import ( # noqa: E402
from .file_find.get_files_from_folder import parse_gitignore as parse_gitignore # noqa: E402
from .file_find.get_files_from_folder import is_gitignored as is_gitignored # noqa: E402
from .file_find.get_files_from_folder import ( # noqa: E402
get_files_in_directory as get_files_in_directory,
)
from .file_find.traverse_files_from_folder import ( # noqa: E402
from .file_find.get_files_from_folder import ( # noqa: E402
get_directory_structure as get_directory_structure,
)
from .file_find.traverse_files_from_folder import ( # noqa: E402
from .file_find.get_files_from_folder import ( # noqa: E402
get_directory_folder_list as get_directory_folder_list,
)
from .file_find.traverse_files_from_folder import ( # noqa: E402
from .file_find.get_files_from_folder import ( # noqa: E402
get_directory_file_list as get_directory_file_list,
)
from .file_find.find_files import find_files_by_name as find_files_by_name # noqa: E402)
from .file_find.find_folders import find_folders_by_name as find_folders_by_name # noqa: E402)

# Folder OP
from .folder_op.create_folder import create_directory as create_directory # noqa: E402
Expand All @@ -36,3 +38,6 @@
## read file
from .file_op.read import read_file as read_file # noqa: E402
from .file_op.read import read_line as read_line # noqa: E402

# utils
from .utils.os_tree import tree as tree # noqa: E402
32 changes: 32 additions & 0 deletions way3/file_find/find_files.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
from typing import List
import os
from way3.utils.ignore_rule import parse_gitignore, is_gitignored


def find_files_by_name(
search_string: str, directory=".", should_ignore=True, ignore_file_path=None
) -> List[str]:
"""
寻找某个路径下,文件名包含某个字符串的所有文件名绝对路径列表
"""
matching_files = []

ignore_file_path = (
ignore_file_path
if ignore_file_path is not None
else os.path.join(".", ".gitignore")
)
gitignore_rules = parse_gitignore(ignore_file_path)

for root, dirs, files in os.walk(directory):
for file in files:
if search_string in file:
file_path = os.path.join(root, file)
# 检查文件路径是否匹配.gitignore中的规则
if should_ignore:
if not is_gitignored(file_path, gitignore_rules):
matching_files.append(file_path)
else:
matching_files.append(file_path)

return matching_files
35 changes: 35 additions & 0 deletions way3/file_find/find_folders.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
from typing import List
import os
from way3.utils.ignore_rule import parse_gitignore, is_gitignored


def find_folders_by_name(
directory: str, search_string: str, should_ignore=True, ignore_file_path=None
) -> List[str]:
"""
寻找某个路径下,文件夹包含某个字符串的所有文件夹列表
"""
matching_folders = []

ignore_file_path = (
ignore_file_path
if ignore_file_path is not None
else os.path.join(".", ".gitignore")
)
gitignore_rules = parse_gitignore(ignore_file_path)

for root, dirs, files in os.walk(directory):
for dir in dirs:
dir_path = os.path.join(root, dir)
# 检查文件夹路径是否匹配.gitignore中的规则
if should_ignore:
if (
not is_gitignored(dir_path, gitignore_rules)
and search_string in dir
):
matching_folders.append(dir_path)
else:
if search_string in dir:
matching_folders.append(dir_path)

return matching_folders
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,9 @@ def get_directory_structure(path) -> Dict[str, Dict[str, List[str]]]:

def get_directory_folder_list(path) -> List[str]:
"""
获取指定路径下的目录结构
获取指定路径下的文件夹列表
:param path: 路径
:return: 目录结构
:return: 文件夹绝对路径列表
"""
directory_structure = get_directory_structure(path)
absolute_path = list(directory_structure.keys())[0]
Expand All @@ -60,9 +60,9 @@ def get_directory_folder_list(path) -> List[str]:

def get_directory_file_list(path) -> List[str]:
"""
获取指定路径下的目录结构
获取指定路径下的文件列表
:param path: 路径
:return: 目录结构
:return: 文件绝对路径列表
"""
directory_structure = get_directory_structure(path)
absolute_path = list(directory_structure.keys())[0]
Expand Down
72 changes: 72 additions & 0 deletions way3/utils/os_tree.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import os


def tree(
directory,
prefix="",
show_hidden=False,
max_depth=None,
full_path=False,
sort_by_size=False,
show_permissions=False,
current_depth=0,
):
# 先获取目录中的所有文件和文件夹
entries = os.listdir(directory)

if not show_hidden:
entries = [entry for entry in entries if not entry.startswith(".")]

if sort_by_size:
entries.sort(key=lambda entry: os.path.getsize(os.path.join(directory, entry)))
else:
entries.sort()

files = []
dirs = []
for entry in entries:
full_path_entry = os.path.join(directory, entry)
if os.path.isdir(full_path_entry):
dirs.append(entry)
else:
files.append(entry)

def format_entry(entry, path):
if full_path:
entry = path
if show_permissions:
entry = f"{oct(os.stat(path).st_mode)[-3:]} {entry}"
return entry

# 打印当前目录下的文件
for file in files:
file_path = os.path.join(directory, file)
print(prefix + "|-- " + format_entry(file, file_path))

# 递归打印子目录
if max_depth is None or current_depth < max_depth:
for i, dir in enumerate(dirs):
dir_path = os.path.join(directory, dir)
print(prefix + "|-- " + format_entry(dir, dir_path))
new_prefix = prefix + "| " if i < len(dirs) - 1 else prefix + " "
tree(
dir_path,
new_prefix,
show_hidden,
max_depth,
full_path,
sort_by_size,
show_permissions,
current_depth + 1,
)


# 使用示例
# tree(
# "./way3",
# show_hidden=True,
# max_depth=2,
# full_path=False,
# sort_by_size=True,
# show_permissions=False,
# )

0 comments on commit b4f8e14

Please sign in to comment.