bash: 스크립트와 터미널의 동작이 다름(루핑 파일)

bash: 스크립트와 터미널의 동작이 다름(루핑 파일)

사례 설명과 함께 사용 중인 폴더를 기반으로 다양한 검색 기준을 사용하여 파일을 반복하려고 합니다. 원래:

#!/bin/bash
case folder in
  "Testordner")
     search_filename=*_0_*.txt
      ;;
  "Ordner2")
     search_filename=*_65_*fg*.txt
     ;;
  *)
     ;;
esac
for files in $search_filename; do
  echo $files
done

나는 Last Echo의 검색 기준과 일치하는 파일 목록을 얻기를 바랐습니다. 대신 검색 기준 자체를 얻습니다.

테스트하기 위해 F="*.txt";for files in $F;do echo $files;donebash(작동하고 파일 목록을 얻음)와 동일한 스크립트(출력을 얻음)에서 직접 시도 했습니다 *.txt . $(..) ((..)) ${..}작동하지 않습니다.)

왜 그런 겁니까? 어떻게 해결할 수 있나요?

기꺼이 도움을 받을 것입니다. 카를로를 기원합니다


Ubuntu 22.04LTS, KDE/플라즈마 데스크탑 v5.1.16(1)을 사용합니다. 터미널: konsole v21.12.3

답변1

Bash에서 nullglob비활성화된 경우(일반적으로 기본값) 일치 항목이 없을 때 전역 패턴은 자체적으로 평가/확장됩니다(예: *.txt리터럴 문자열로 평가 ). *.txt활성화되면 nullglob(일반적으로 스크립트에 더 적합함) 일치하는 항목이 없을 경우 전역 패턴이 빈 문자열로 평가/확장됩니다.

스크립트가 다른 디렉터리에서 실행되면 glob이 다르게 확장됩니다(물론 각 디렉터리에 동일한 파일 이름이 존재하지 않는 한).

예를 들어:

user@host:~ 0 $ touch {a,b,c}.log
user@host:~ 0 $ ls -l
total 0
-rw-------  1 user  staff  0 Jul 25 10:27 a.log
-rw-------  1 user  staff  0 Jul 25 10:27 b.log
-rw-------  1 user  staff  0 Jul 25 10:27 c.log
user@host:~ 0 $ shopt nullglob
nullglob        off
user@host:~ 1 $ echo *.log
a.log b.log c.log
user@host:~ 0 $ echo *.bak
*.bak
user@host:~ 0 $ shopt -s nullglob
user@host:~ 0 $ shopt nullglob
nullglob        on
user@host:~ 0 $ echo *.log
a.log b.log c.log
user@host:~ 0 $ echo *.bak

user@host:~ 0 $ 

관련 없는 메모에서... 적어도 적절한 경우 명령줄 안전성과 공백 처리를 개선하는 echo "$files"대신 의도적인 인용을 관용적으로 만드는 것을 고려해 보십시오.echo $files

예를 들어, 관심이 있다면 배열을 사용할 수도 있습니다.

#!/bin/bash -e

export PATH=/bin:/sbin:/usr/bin:/usr/sbin
shopt -s nullglob

declare -a files=()
case "$1" in
    'logs')
        files=(*.log)
        ;;
    'baks')
        files=(*.bak)
        ;;
    *)
        echo 'invalid argument' 1>&2
        exit 1
        ;;
esac

for f in "${files[@]}"; do
    echo "$f"
done

관련 정보