我试图在一堆具有以下形式的子目录中找到所有文件:
sub-num_ses-wavenum_task-name_run-num_info.ext
或
sub-num_ses-wavenum_task-name_info.ext
文件名run-num
的部分可以采用run-01
到run-15
或更高的格式,具体取决于匹配task-name
段的数字文件。如果没有重复的任务名称,则没有run-num
。
脚本可以成功输入目录,我可以通过在_
分隔
niidir="some/path"
for dirpath, dirnames, files in os.walk(niidir):
for dirname in dirnames:
if dirname == "fmap" or dirname == "anat" or dirname == "func":
fullpath = dirpath + "/" + dirname
for files in fullpath:
for file in os.listdir(fullpath):
chunks = file.split("_")
print(chunks)
print(chunks)
将给出输出:
['sub-num', 'ses-wavenum', 'task-name', 'run-num', 'info.ext']
或者,如果没有run-num
:
['sub-num', 'ses-wavenum', 'task-name', 'info.ext']
我也可以打破我要检查的部分,看看它是否是一个运行编号:
niidir="some/path"
for dirpath, dirnames, files in os.walk(niidir):
for dirname in dirnames:
if dirname == "fmap" or dirname == "anat" or dirname == "func":
fullpath = dirpath + "/" + dirname
for files in fullpath:
for file in os.listdir(fullpath):
chunks = file.split("_")
print(chunks[-2])
退货,例如:
run-02
,如果有运行编号,或者是
task-name
,如果没有运行编号。
但是,我的问题是我似乎无法列出仅那些有运行编号的文件:
niidir="some/path"
for dirpath, dirnames, files in os.walk(niidir):
for dirname in dirnames:
if dirname == "fmap" or dirname == "anat" or dirname == "func":
fullpath = dirpath + "/" + dirname
for files in fullpath:
for file in os.listdir(fullpath):
chunks = file.split("_")
if chunks[-2]) == glob.glob("run-[0-9]{2}"):
print(chunks[-2])
根本没有输出。
我不知道为什么我找不到匹配的刺痛。
编辑1:
文件路径为niidir/sub-num/ses-num/sequence/files
clean_nii中有多个子num目录,每个子num目录中有多个ses-num目录。每个ses-num目录包含以下部分或全部序列目录:“anat”,“func”或“fmap”,其中包含文件。
编辑2:我不是程序员。请不要假设我知道你在说什么,即使它是“基本的”。我正在努力。
答案 0 :(得分:0)
您对glob使用了错误的语法,并且您正在错误地使用通配符。您的glob()
调用想要在单个数字后匹配文字{2}
字符串,并且您尝试使用生成文件列表的函数来测试字符串是否与模式匹配。
匹配文件的正确模式是:
glob.glob("run-[0-9][0-9]*")
Glob模式不是正则表达式。有关详细信息,请参阅wikipedia article on glob syntax和fnmatch
module。
接下来,glob.glob()
查找文件系统上的文件,并返回匹配文件名的列表。上述模式没有路径信息,因此只列出本地工作目录中的文件。您必须使用glob.glob(os.path.join(fullpath, "run-[0-9][0-9]*")
来匹配目录中的特定文件,此时列表将包含完整路径。您不应该将该列表与单个字符串进行比较,chunks[-2]
从不将等于匹配文件名列表。
如果你想看看你的字符串是否与特定的通配模式匹配,你可以使用fname.fnmatch()
function:
if fnmatch.fnmatch(chunks[-2], 'run-[0-9][0-9]'):
现在,您实际上正在测试文件名部分是否包含开头的字符串run-
,后跟两位数。
接下来,您的for files in fullpath
循环遍历fullpath
字符串的个别字符。你重复这个循环len(filepath)
次,而不需要重复任何事情。你忽略了files
变量,你只是做了不必要的额外工作。
接下来,您的代码仍在执行超出其需要的工作。 os.walk()
已列出目录中的文件名,但您的代码会通过os.listdir()
调用冗余地列出它们。在找到这些特定子目录后修剪dirnames
列表,或者为匹配的子目录测试dirpath
并改为处理files
:
import os
import os.path
import fnmatch
niidir="some/path"
for dirpath, dirnames, files in os.walk(niidir):
directory_name = os.path.basename(dirpath)
if directory not in {'fmap', 'anat', 'func'}:
# Only process files in specific subdirectories
continue
for filename in fnmatch.filter(files, "run-[0-9][0-9]*"):
# process matching file
我使用fnmatch.filter()
function过滤掉files
生成的os.walk()
列表中的匹配名称。
或者,如果您要处理目录中的所有文件并仅测试较大列表中的特定文件,请坚持fnmatch.fnmatch()
:
for dirpath, dirnames, files in os.walk(niidir):
directory_name = os.path.basename(dirpath)
if directory not in {'fmap', 'anat', 'func'}:
# Only process files in specific subdirectories
continue
for filename in files:
prefix, remainder = filename.partition('_')
if fnmatch.fnmatch(prefix, 'run-[0-9][0-9]'):
# filename starts with a run-number.
else:
# do something else