如何获得与目录及其子目录相同的规则

时间:2019-06-18 07:49:39

标签: snakemake

我正在尝试制定一条规则,该规则在目录及其子目录中的任何一个上都将起作用(以避免多次重复该规则)。如果有一个子目录,我想访问它。

我的方法是使子目录为可选。鉴于可以通过显式给出“。*”模式使通配符接受空字符串,因此我尝试了以下规则:

rule test_optional_sub_dir:
    input:
        "{adir}/{bdir}/a.txt"
    output:
        "{adir}/{bdir,.*}/b.txt"
    shell:
        "cp {input} {output}"

我希望该规则能够与A / b.txt和A / B / b.txt匹配。

但是,A / b.txt与规则不匹配。 (A // b.txt也不是bdir的遗漏,我猜double /在匹配发生之前就被删除了。)

以下规则适用于A / b.txt和A / B / b.txt:

rule test_optional_sub_dir2:
    input:
        "{path}/a.txt"
    output:
        "{path,.*}/b.txt"
    shell:
        "cp {input} {output}"

,但是在这种情况下的问题是我无法轻松访问path中目录的名称。我可以使用函数pathlib.Path分解{path},但这似乎变得太复杂了。

是否有更好的方法来完成我想做的事情?

非常感谢您的帮助。

2 个答案:

答案 0 :(得分:1)

经过进一步的摆弄,我发现了一些接近我想要的东西: 假设我要至少一个目录,并且在其下不超过2个可选目录。以下作品。唯一的缺点是opt_dir1和opt_dir2包含尾部斜杠,而不仅仅是目录名。

rule test_optional_sub_dir3:
    input:
        "{mand_dir}/{opt_dir1}{opt_dir2}a.txt"
    output:
        "{mand_dir}/{opt_dir1}{opt_dir2}b.txt"
    wildcard_constraints:
        mand_dir="[^/]+",
        opt_dir1="([^/]+/)?",
        opt_dir2="([^/]+/)?"
    shell:
        "cp {input} {output}"

如果有人拥有,仍然对更好的方法感兴趣。

答案 1 :(得分:1)

您要在规则中使用子目录的确切方式可能会确定执行此操作的最佳方法。也许像这样:

def get_subdir(path):
    dirs = path.split('/')
    if len(dirs) > 1:
        return dirs[1]
    else:
        return ''

rule myrule:
    input:
        "{dirpath}/a.txt"
    output:
        "{dirpath}/b.txt"
    params:
        subdir = lambda wildcards: get_subdir(wildcards.dirpath)
    shell:
        #use {params.subdir}

当然,如果您的规则使用“运行”或“脚本”而不是“外壳”,则您甚至不需要该函数和subdir参数,只需从通配符中找出传递给脚本。