*.sh를 사용하여 서로 다른 디렉터리에 있는 여러 .sh 파일을 실행하는 방법

*.sh를 사용하여 서로 다른 디렉터리에 있는 여러 .sh 파일을 실행하는 방법

.sh디렉터리 패턴에 있는 모든 파일을 실행할 수 있는 쉘 스크립트를 작성해야 합니다 . 그것은 다음과 같습니다:

##!/bin/bash
sh /var/scripts/*/my_*.inc.sh

그러나 위의 스크립트는 하나의 파일만 실행합니다. 발생하는 첫 번째 파일(마지막 수정 날짜에 의해 선택된 것으로 보임)은 내 요점이 아닙니다. 규칙과 일치하는 모든 파일을 실행해야 합니다.

답변1

코드가 작동하지 않는 이유는 파일 이름 와일드카드 패턴이 확장될 때 발생하기 때문입니다.

이 모델은 다음으로 확장됩니다.목록일치하는 경로 이름. 스크립트의 코드는 sh이 목록을 사용하여 호출합니다. 이는 첫 번째로 일치하는 이름을 스크립트로 실행하고 다른 이름을 다음과 같이 지정함을 의미합니다.논쟁이 스크립트에:

sh /var/scripts/dir/my_first.inc.sh /var/scripts/dir/my_second.inc.sh /var/scripts/dir/my_third.inc.sh

대신 일치하는 이름을 반복하면 됩니다.

#!/bin/sh

for name in /var/scripts/*/my_*.inc.sh; do
    sh "$name"
done

sh이는 일치하는 각 이름이 실행되어야 하는 (아님 ) 스크립트라고 가정합니다 bash. 해당 파일이 실행 가능하고 올바른 행을 갖고 있는 경우 위 루프의 스크립트 호출에서 해당 파일을 제거하십시오 #!. sh파일이 "도트 스크립트", 즉 소스를 제공해야 하는 스크립트인 경우 스크립트가 현재 스크립트의 컨텍스트에서 실행되도록 하려면 다음으로 sh바꾸 십시오..

위 스크립트는 어떤 기능도 사용하지 않으므로 shscript( )일 수 있습니다 . 다른 스크립트가 "도트 스크립트"인 경우 스크립트를 얻으려면 분명히 이를 변경해야 하거나 다른 인터프리터가 필요할 수 있습니다.#!/bin/shbash#!/bin/bash

답변2

확장자는 .inc.sh이러한 .inc.sh파일이 다음과 같아야 함 을 나타냅니다.포함하다즉, 해당 내용은 쉘 코드로 평가되어야 합니다.하나동일한 쉘 인터프리터를 사용할 수 있도록 하는 쉘 인터프리터기능,변하기 쉬운,별명...사용 가능한 파일에 정의되어 있습니다.

bash그들의 sh문법 .bashshshshbash

bash(POSIX 모드가 아닌 경우) 및 사이의 중요한 차이점 중 하나 는 스크립트에서 확장을 지원하지 않는다는 sh것입니다 . 그러나 이는 옵션이나 옵션을 설정하여 해결할 수 있으므로 다음과 같이 할 수 있습니다.bashaliasexpand_aliasesposix

#! /bin/bash -
set -o posix # increase POSIX sh compatibility, some but not all bash-specific
             # extensions are still available.

for file in /var/scripts/*/my_*.inc.sh; do
  . "$file"
done

# rest of the code that uses the functions/variables, etc defined
# in the files sourced above with the "." special builtin

일치하는 파일이 없으면 문자 .그대로 존재하지 않는 파일을 가져오고 셸을 종료하려고 하면 /var/scripts/*/my_*.inc.sh명령이 실패합니다 .

이 경우 아무것도 하고 싶지 않다면 다음을 수행할 수 있습니다.

shopt -s nullglob
files=(/var/scripts/*/my_*.inc.sh)
shopt -u nullglob

for file in "${files[@]}"; do
  command . "$file"
done

를 사용하면 nullglob일치하지 않는 glob이 확장되지 않은 패턴이 아닌 빈 목록으로 확장됩니다. 접두어를 사용하면 command특수 내장 함수의 실패 .(예: $file읽을 수 없는 경우)로 인해 쉘이 종료되지 않습니다(오류는 계속 보고되어야 합니다).

.inc.sh하위 디렉터리 대신 반복적으로 파일을 찾으려면 /var/scripts이 옵션을 사용하여 연산자를 globstar활성화 할 수 있습니다.**

shopt -s nullglob globstar
files=(/var/scripts/**/my_*.inc.sh)
shopt -u nullglob globstar

.어떤 경우에도 이름이 (hidden)으로 시작하는 디렉터리와 파일은 생략됩니다. dotglob다음을 포함하려면 이 옵션을 사용하십시오.

분명히, 소스 스크립트가 실패 내에서 호출되거나 구문 오류가 있거나 특수 내장 함수가 호출되는 경우 exit스크립트 exec도 종료됩니다.

답변3

쉘 스크립트(bash 포함)에서 파일을 반복하는 가장 안전한 방법은 for 루프에서 경로 이름 확장(와일드카드)을 사용하는 것입니다. 올바른 코드는 다음과 같습니다:

for file in /var/scripts/*/my_*.inc.sh
do
  echo "Executing $file"
  "$file"
done

공백, 별표, 줄 바꿈 등과 같은 특수 문자가 포함된 경로와 파일 이름을 처리합니다.

재귀 검색을 원하거나 globbing에서 사용할 수 없는 옵션을 사용하려는 경우 -exec이 옵션과 함께 find를 사용할 수 있습니다(다음에서는 최근 GNU 찾기를 가정합니다).

find a/ -executable -type f -name '*.sh' -exec {} \;

find가 여전히 필요하지만 각 파일에서 여러 명령을 실행하려는 경우 이를 read사용할 수 있지만 모든 파일 이름에 대한 옵션에 주의해야 합니다(다음에서는 bash 및 GNU find를 가정합니다).

#!/bin/bash
find a/ -executable -type f -name '*.sh' -print0 |
  while IFS= read -r -d $'\0' file
  do
    echo "Executing $file"
    "$file"
  done

답변4

다음과 같이 for루프를 (재귀적으로) 사용하여 찾은 경로의 모든 셸 파일을 반복 할 수 있습니다 .find

for i in $(find /var/scripts/ -type f -name '*.sh')
  do sh "$i"
done

관련 정보