폴더에 확장자를 가진 파일이 포함되어 있는지 확인하고 디렉터리를 범주에 기록합니다.

폴더에 확장자를 가진 파일이 포함되어 있는지 확인하고 디렉터리를 범주에 기록합니다.

약 3,000개 이상의 폴더가 있고 여기에는 단일 스프링 파일과 한 쌍의 fastq.gz 파일이라는 두 가지 유형의 파일이 있을 수 있습니다. 폴더를 스캔하고 파일 확장자 중 하나 또는 둘 모두가 디렉터리에 있는지 알고 싶습니다.

  1. fastq.gz 및 spring 파일 쌍을 포함합니다.
  2. fastq.gz 파일 1개와 스프링 파일 1개
  3. 단일 스프링 파일
  4. fastq.gz 파일 쌍
  5. 단일 fastq.gz 파일

사용했지만 오류가 [ /path/to/dir/*fastq.gz ]발생 unary operator expected하고 사용이 [[ ]]올바르게 테스트되지 않는 것 같습니다.

내가 사용한 실제 스크립트는 -

check_dir () {
in="$1"
echo "$in Checking for spring"
[ "$in"/*spring -f ] && echo "$in"
}
export -f check_dir

저는 bash를 사용하고 있습니다. 논리에 대한 도움을 주시면 감사하겠습니다.

답변1

unary operator expected[*(는) 독립적으로 작동하기 때문입니다 *fastq.gz.

[쉘 구문이 아닙니다. [일반 명령(Bash에 내장되어 있지만 여전히 명령임)이며 ]마지막 명령입니다.논쟁, 필수 항목입니다. 그 사이의 모든 것도 논쟁입니다.

쉘은 /path/to/dir/*fastq.gz호출하기 전에 하나 이상의 단어로 확장됩니다 [. [이 단어와 필수 단어를 ]인수로 볼 것입니다. 인수 수와 인수에 따라 [0개 이상의 인수가 연산자(예: -f)가 될 것으로 예상됩니다.

단일 인수로 확장되면 유효 [ /path/to/dir/*fastq.gz ]합니다 /path/to/dir/*fastq.gz("유효할 것입니다"는 "원하는 것을 수행할 것입니다"와 동일하지 않음). 여기에는 일치하는 항목이 없는 경우도 포함됩니다 *. 전통적으로(Bash에서는 기본적으로) 일치하는 항목이 없으면 /path/to/dir/*fastq.gz있는 그대로 처리됩니다. 여러 단어로 확장 될 수 있으며 /path/to/dir/*fastq.gz그 중 어느 것도 운영자가 이해하는 것처럼 보이지 않습니다 [. 발생한 오류는 패턴이 두 단어로 확장된 경우에 발생했을 가능성이 높습니다.

나중에 [ "$in"/*spring -f ]. 이것은 훨씬 더 나쁩니다. 아마도 당신이 [ -f some/path ]어디에 -f있는지 같은 것을 원했기 때문입니다.~ 전에테스트할 경로입니다. 여전히 [ -f "$in"/*spring ]강력한 수정 사항은 아닙니다."$in"/*spring 일반적으로여러 가지 주장으로 확장될 수 있으며 [이를 견디지 ​​못할 수 있습니다. 디렉터리당 최대 하나의 파일이 있다고 썼 *spring으므로당신의 경우에는이와 같은 코드는 어느 정도 작동할 수 있습니다. 그래도 여전히 열악한 코드입니다.

에서는 여러 단어로 확장될 수 있는 [와일드카드를 사용하지 마십시오 . *이는 즉시 또는 곧 실패합니다.[[후드 아래는 다릅니다하지만 그것은 당신의 목적에도 좋지 않습니다.

패턴과 일치하는 파일 수를 알고 싶습니다 /path/to/dir/*fastq.gz. 이를 수행하는 올바른 방법은 확장 결과를 배열에 할당하는 것입니다. 이식 가능한 배열은 하나뿐입니다. 즉, 쉘 스크립트(또는 쉘 함수)의 인수 배열입니다. 일치 항목이 0인 경우를 감지하려면 추가 코드가 필요합니다(이 경우에도 확장되지 않은 패턴 문자열이라는 하나의 단어가 생성됩니다). 귀하의 질문에 태그가 지정되었습니다., 따라서 명명된 배열과 기타 이식 불가능한 기능을 사용할 것입니다.

# non-portable code, works in Bash
check_dir () (
   dir="${1-.}"
   dir="${dir%/}/"
   [ -d "$dir" ] || { echo "Not a directory." >&2; return 1; }
   shopt -s nullglob
   files=( "$dir"/*fastq.gz )
   nf="${#files[@]}"
   files=( "$dir"/*spring )
   ns="${#files[@]}"
   printf '%s\t%s\t%s\n' "$nf" "$ns" "$dir"
)

사용법: check_dir path/to/dir또는 check_dir(기본 경로는 .). 이 함수는 파일 수 *fastq.gz, 탭, 파일 수 *spring, 탭, 마지막으로 검사된 경로(뒤에 로 인쇄됨 /)를 인쇄합니다.

이제 디렉토리 트리를 분석할 수 있습니다(아래 함수를 사용하려면 위 함수를 정의해야 합니다).

# non-portable code, works in Bash
check_dirs () (
   dir="${1-.}"
   dir="${dir%/}/"
   [ -d "$dir" ] || { echo "Not a directory." >&2; return 1; }
   shopt -s nullglob globstar
   for d in "$dir"**/; do
      check_dir "$d"
   done
)

사용법: check_dirs path/to/dir또는 check_dirs(기본 경로는 .).

노트:

  • 큰 디렉토리 트리의 경우 check_dirs처음에는 정지된 것처럼 보일 수 있습니다. 이는 호출되어 무엇이든 인쇄하기 for d in "$dir"**/전에 완전히 확장되어야 하기 때문입니다.check_dir

  • 함수는 의도적으로 하위 쉘( check_dir () (과 반대 check_dir () {)로 정의되므로 쉘 옵션( shopt)과 모든 변수는 로컬입니다.

  • 숨겨진 파일 수를 계산 하려면 이 기능이 check_dir필요합니다 dotglob(예 shopt -s nullglob dotglob: ).

  • 숨겨진 디렉토리로 내려 가려면 이 기능이 check_dirs필요합니다 dotglob(예 shopt -s nullglob globstar dotglob: ).

  • 디렉터리 이름에 개행 문자가 포함되어 있지 않으면 표준 도구를 사용하여 check_dir또는 의 출력을 쉽게 구문 분석할 수 있습니다. check_dirs유용한 명령: sort -n, grep $'^2\t1\t', cut -f 3-.

    ./예를 들어 정확히 하나의 *fastq.gz파일과 정확히 0개의 파일이 있는 디렉터리를 찾으려면 다음을 수행합니다 *spring.

    check_dirs | grep $'^1\t0\t' | cut -f 3-
    

관련 정보