두 개의 확장자를 가진 파일 이름을 확인하는 쉘 스크립트. 두 확장자를 모두 가진 파일이 있으면 스크립트를 호출하십시오. 그렇지 않으면 실패합니다.

두 개의 확장자를 가진 파일 이름을 확인하는 쉘 스크립트. 두 확장자를 모두 가진 파일이 있으면 스크립트를 호출하십시오. 그렇지 않으면 실패합니다.

두 가지 확장명(.txt 및 .ctl)을 가진 파일이 있는지 디렉터리를 확인하고 파일이 두 가지 확장자를 모두 가진 경우 스크립트를 호출해야 합니다. 그렇지 않으면 작업이 실패합니다. 몇 가지를 시도했지만 예상대로 작동하지 않습니다. 누구든지 나를 도와줄 수 있나요?

답변1

#!/bin/bash

# Assuming the directory is passed to us as an argument...
DIR="$1"
SCRIPT=/path/to/the/other/script.sh

COUNT=0
for i in "$DIR"/*.txt "$DIR"/*.ctl ;do
  if [ -f "$i" ] ;then # this is a regular file
    ((COUNT++))
    "$SCRIPT" "$i"
  fi
done

if [ $COUNT -eq 0 ] ;then
   exit 1 # No .txt or .ctl files were found.
fi

질문은 그다지 명확하지 않으므로 특정 디렉터리의 모든 파일에 이 두 가지 확장자가 있는지 확인하고 싶다고 가정합니다.

답변2

정확히 무엇을 확인하고 싶은지 명확하지 않습니다. 다음은 zsh셸에서 문제를 해결하는 몇 가지 방법입니다 .

#! /bin/zsh -

for dir do
  txt=($dir/*.txt(ND:t:r))
  ctl=($dir/*.ctl(ND:t:r))
  both=("${(@)txt:*ctl}")
  txt_but_not_ctl=("${(@)txt:|ctl}")
  ctl_but_not_txt=("${(@)ctl:|txt}")

  print -r -- "$dir has $#txt file${txt[2]+s} with a .txt extension"
  print -r -- "$dir has $#ctl file${ctl[2]+s} with a .ctl extension"
  print -r -- "$#both .txt file${both[2]+s} in $dir have matching files with the same root name and a .ctl extension"
  print -r -- "$dir has $#txt_but_not_ctl .txt file${txt_but_not_ctl[2]+s} without a corresponding .ctl file"
  print -r -- "$dir has $#ctl_but_not_txt .ctl file${ctl_but_not_txt[2]+s} without a corresponding .txt file"

  (($#both && $#txt_but_not_ctl == 0 && $#ctl_but_not_txt == 0)) &&
    print -r -- "all the .txt files in $dir have a corresponding .ctl file and vis versa"
done

여기서 관심 있는 주요 구조는 다음과 같습니다.

  • files=(*(DN)): 패턴과 일치하는 파일 목록을 배열 변수에 할당합니다. D숨겨진 목록을 포함하며 N빈 목록( nullglob)을 허용합니다.
  • :t:r,선택하다머리(목차 섹션 제거) 및뿌리확장 프로그램을 제거하세요.
  • ${A:*B}두 배열의 교차점입니다. "${(@)A:*B}"빈 요소를 유지합니다(예: .txt또는이라는 파일이 있는 경우 .ctl).
  • ${A:|B}두 개의 배열( A가운데에 있지 않은 요소 B)을 뺍니다.
  • $#array:배열의 요소 수입니다.
  • (( arithmetic expression ))산술 표현식을 평가하고 반환합니다.진짜결과가 0이 아닌 경우.

최신 GNU 기반 시스템을 사용하고 있다면 다음을 수행할 수 있습니다 bash(더 서투르고 힘들고 덜 효율적이긴 하지만).

#! /bin/bash -
shopt -s nullglob dotglob

printz() {
  (($# == 0)) || printf '%s\0' "$@"
}

for dir do
  txt=("$dir"/*.txt)
  txt=("${txt[@]##*/}")
  txt=("${txt[@]%.*}")
  ctl=("$dir"/*.ctl)
  ctl=("${ctl[@]##*/}")
  ctl=("${ctl[@]%.*}")

  readarray -td '' both < <(
    LC_ALL=C comm -z12 <(printz "${txt[@]}" | LC_ALL=C sort -z) \
                       <(printz "${ctl[@]}" | LC_ALL=C sort -z))
  readarray -td '' txt_but_not_ctl < <(
    LC_ALL=C comm -z13 <(printz "${txt[@]}" | LC_ALL=C sort -z) \
                       <(printz "${ctl[@]}" | LC_ALL=C sort -z))
  readarray -td '' ctl_but_not_txt < <(
    LC_ALL=C comm -z23 <(printz "${txt[@]}" | LC_ALL=C sort -z) \
                       <(printz "${ctl[@]}" | LC_ALL=C sort -z))

  printf '%s\n' "$dir has ${#txt[@]} file${txt[2]+s} with a .txt extension"
  printf '%s\n' "$dir has ${#ctl[@]} file${ctl[2]+s} with a .ctl extension"
  printf '%s\n' "${#both[@]} .txt file${both[2]+s} in $dir have matching files with the same root name and a .ctl extension"
  printf '%s\n' "$dir has ${#txt_but_not_ctl[@]} .txt file${txt_but_not_ctl[2]+s} without a corresponding .ctl file"
  printf '%s\n' "$dir has ${#ctl_but_not_txt[@]} .ctl file${ctl_but_not_txt[2]+s} without a corresponding .txt file"

  ((${#both[@]} && ${#txt_but_not_ctl[@]} == 0 && ${#ctl_but_not_txt[@]} == 0)) &&
    printf '%s\n' "all the .txt files in $dir have a corresponding .ctl file and vis versa"
done

어디:

  • ND전역 nullglobdotglob옵션 으로 대체 됩니다 .
  • :t"${array[@]##*/}"패턴 스트리핑 ksh 연산자 사용
  • :r"${array[@]%*/}"패턴 스트리핑 ksh 연산자 사용
  • 배열 결합 및 빼기는 NUL로 구분된 레코드가 있는 C 로케일에서 sort+를 사용하여 수행 됩니다 comm(NUL은 파일 이름(또는 bash 변수)에서 찾을 수 없는 유일한 바이트입니다).

관련 정보