ubuntu 如何在Linux中查找包含具有一个扩展名的文件而不包含具有另一个扩展名的文件的目录

ylamdve6  于 2023-02-03  发布在  Linux
关注(0)|答案(2)|浏览(228)

我必须过滤掉大量包含扩展名为.spring的文件(两个fastq文件的压缩文件)的目录/路径。但在其中一些目录中,. fastq.gz文件仍然存在。我需要获取那些只有.spring文件而没有. fastq.gz文件的目录的路径。(具体来说,我需要获取那些.spring文件的路径)。
我试过使用find命令,但是不知怎么的,它并不像我想要的那样工作。请给予一些建议
另外,如何检查目录是否同时包含文件- .fastq.gz和.spring?
谢谢
我尝试了以下方法:

find $(find $PWD -name "*.spring" -printf '%h\\n') -not -name  "*.fastq.gz"
2ic8powd

2ic8powd1#

下面是一个返回所需列表的bash脚本:

#!/bin/bash
set -euo pipefail
IFS=$'\n\t'

# find all directories containing *.spring files
spring_dirs=$(find $PWD -type f -name '*.spring' -exec dirname {} \; | sort -u)

# within the directories containing *.spring files,
# find those directories that also contain *.fastq.gz files,
# but use -maxdepth 1 to not look any deeper than the *.spring file dir
fastq_dirs=$(find $spring_dirs -maxdepth 1 -type f -name '*.fastq.gz' -exec dirname {} \; | sort -u)

# concatenate the two sets of directories and only keep the ones
# that are not repeated
spring_only_dirs=$(printf "%s\n%s\n" "$spring_dirs" "$fastq_dirs" | sort | uniq -u)

# use the directories of *.spring files to get the full
# file names of the *.spring files
find $spring_only_dirs -maxdepth 1 -type f -name '*.spring'

这不是最快的方法,但希望容易理解并且相当短。正如注解中所指出的,如果文件名或路径中有空格(或新行),此方法将失败。虽然可以在bash中处理包含空格的文件名,但这将使脚本明显更长和更复杂。
下面是python中一个更健壮的实现:

#!/usr/bin/env python

from os import walk
from pathlib import Path

MUST_CONTAIN_GLOB = '*.spring'
NOT_CONTAIN_GLOB = '*.fastq.gz'
out_files = [str(f)
             for root, _, _ in walk(".")
             for f in Path(root).glob(MUST_CONTAIN_GLOB)
             if not list(Path(root).glob(NOT_CONTAIN_GLOB))]
print("\n".join(out_files))
wqsoz72f

wqsoz72f2#

这是我用函数形式实现的方法。它需要2个参数,它们是要搜索的扩展名。$1是应该存在的文件 $2*是不应该存在于文件夹 * 中的文件。在本例中,它们应该是$1 = spring$2 = fastq.gz**

findExcludingIncludingDirs () {
    local Dirs=( `find . -type d` )
    local Dir typesA typesB

    local Files=() Directories=()
    
    for Dir in $Dirs; do
        if [[ $Dir = '.' ]]; then continue; fi

        typesA=( `find "${Dir}" -maxdepth 1 -name "*.${1}" -type f 2>/dev/null` )
        typesB=( `find "${Dir}" -maxdepth 1 -name "*.${2}" -type f 2>/dev/null` )
        
        if [[ ${#typesA[@]} -gt 0 ]]; then
            Files+=( ${typesA[@]} )
            if [[ ${#typesB[@]} -gt 0 ]]; then Directories+=( "${Dir}" ); fi
        fi
    done;
}; alias feid="findExcludingIncludingDirs"

**目录*将包含所有目录
***类型[A|B]**将在当前循环文件夹中保留具有排队扩展名的文件(由于maxdepth,因此不会递归)。此行还将通过 * 2〉/dev/null * 将没有一致文件的文件夹的错误从 * stderr * 输出到 * nobee *
**文件
将保存所有Spring文件(扩展名为$1的文件)
**目录
将包含所有包含这两种文件类型的目录

您可以***操纵函数***来处理数组,或者***将它们保存在一个超出作用域的***var中,以便在函数之后处理它们。
在加载函数后,只需从你想要搜索的路径调用它。使用以下两种形式中的任意一种:

  • > feid spring fastq.gz
  • > findExcludingIncludingDirs spring fastq.gz

别名***feid***只是为了简化写入命令
我的方法已经在OSx zsh env下测试过了,希望能有所帮助,问候!

编辑:

您可以在函数的顶部添加一个安全层来执行一些测试:

if [[ $# -ne 2 ]]; then
    echo "2 extensions are needed, use as folows: 'feid ext1 ext2'"
    return 2
elif [[ "$@" =~ ^.*[\/\:].*$ ]]; then
    echo "Extensions should not be paths"
    return 2
fi

相关问题