搜索与列表中的任何字符串匹配的文件?
Search for files that match any strings from a list?
我想递归遍历一个目录,找到与给定列表中的 任意 字符串匹配的文件,然后将这些文件复制到另一个文件夹。我认为 any() 函数可以完成此操作,但我得到一个 TypeError,它需要一个字符串,而不是一个列表。有没有更优雅的方法来做到这一点?
string_to_match = ['apple.txt', 'pear.txt', 'banana.txt']
for root, subdirs, filename in os.walk(source_dir)
if any(s in filename for s in string_to_match):
shutil.copy(filename, destination_dir)
print(filename)
我知道 glob.glob 可以很好地查找与特定字符串或模式匹配的文件,但我一直无法找到允许多个匹配的答案。
你可以直接使用in
示例:
string_to_match = ['apple.txt', 'pear.txt', 'banana.txt']
for root, subdirs, filename in os.walk(source_dir)
if filename in string_to_match:
shutil.copy(filename, destination_dir)
print(filename)
这里还有一个 glob 版本:
import glob
import itertools
root_dir = '/home/user'
files = ['apple.txt', 'pear.txt', 'banana.txt']
files_found = list(itertools.chain.from_iterable([glob.glob(f'{root_dir}/**/{f}', recursive=True) for f in files])
for f in files_found:
shutil.copy(f, destination_dir)
首先,在列表中找到一个元素的时间复杂度为O(n),因此只需将其转换为一个时间复杂度为O(1)的集合即可。
那你可以这样做
string_to_match = {'apple.txt', 'pear.txt', 'banana.txt'}
for filename in os.listdir(source_dir):
if filename in string_to_match:
shutil.copy(filename, destination_dir)
print(filename)
我会用套装
def find_names(names,source_dir):
names = set(names)
# note os.walk will walk the subfolders too
# if you just want that source_dir use `strings_to_match.intersection(os.listdir(sourcedir))`
for root,subdirs,fnames in os.walk(sourcedir):
for matched_name in strings_to_match.intersection(fnames):
yield os.path.join(root,matched_name)
strings_to_match = ['apple.txt', 'pear.txt', 'banana.txt']
for match in find_names(strings_to_match,'/path/to/start'):
print("Match:", match)
[已编辑] 打字错误 intersection
不是 intersect
(您也可以只传入集合 {'a','b','c'}
而不是列表 ['a','b','c']
并跳过到集合的转换)
这是一个只在源目录(而不是子目录)中查找的替代方法
def find_names_in_folder(names,source_dir):
return [os.path.join(source_dir,n) for n in set(names).intersection(os.listdir(source_dir))]
我想递归遍历一个目录,找到与给定列表中的 任意 字符串匹配的文件,然后将这些文件复制到另一个文件夹。我认为 any() 函数可以完成此操作,但我得到一个 TypeError,它需要一个字符串,而不是一个列表。有没有更优雅的方法来做到这一点?
string_to_match = ['apple.txt', 'pear.txt', 'banana.txt']
for root, subdirs, filename in os.walk(source_dir)
if any(s in filename for s in string_to_match):
shutil.copy(filename, destination_dir)
print(filename)
我知道 glob.glob 可以很好地查找与特定字符串或模式匹配的文件,但我一直无法找到允许多个匹配的答案。
你可以直接使用in
示例:
string_to_match = ['apple.txt', 'pear.txt', 'banana.txt']
for root, subdirs, filename in os.walk(source_dir)
if filename in string_to_match:
shutil.copy(filename, destination_dir)
print(filename)
这里还有一个 glob 版本:
import glob
import itertools
root_dir = '/home/user'
files = ['apple.txt', 'pear.txt', 'banana.txt']
files_found = list(itertools.chain.from_iterable([glob.glob(f'{root_dir}/**/{f}', recursive=True) for f in files])
for f in files_found:
shutil.copy(f, destination_dir)
首先,在列表中找到一个元素的时间复杂度为O(n),因此只需将其转换为一个时间复杂度为O(1)的集合即可。
那你可以这样做
string_to_match = {'apple.txt', 'pear.txt', 'banana.txt'}
for filename in os.listdir(source_dir):
if filename in string_to_match:
shutil.copy(filename, destination_dir)
print(filename)
我会用套装
def find_names(names,source_dir):
names = set(names)
# note os.walk will walk the subfolders too
# if you just want that source_dir use `strings_to_match.intersection(os.listdir(sourcedir))`
for root,subdirs,fnames in os.walk(sourcedir):
for matched_name in strings_to_match.intersection(fnames):
yield os.path.join(root,matched_name)
strings_to_match = ['apple.txt', 'pear.txt', 'banana.txt']
for match in find_names(strings_to_match,'/path/to/start'):
print("Match:", match)
[已编辑] 打字错误 intersection
不是 intersect
(您也可以只传入集合 {'a','b','c'}
而不是列表 ['a','b','c']
并跳过到集合的转换)
这是一个只在源目录(而不是子目录)中查找的替代方法
def find_names_in_folder(names,source_dir):
return [os.path.join(source_dir,n) for n in set(names).intersection(os.listdir(source_dir))]