저는 공백이 있는 경로를 다루고 있습니다.
나는 이런 식으로 글로빙을 수행합니다(두 번째 줄이 글로빙을 설정합니다):
IFS=$'\n'
VAR="$1/"name_*
for file in $VAR; do
echo $file
grep ITEM "$file" | wc -l
done
여기서 설정한 값을 사용 하면 파일 이름의 공백으로 인해 오류가 발생하는 것을 방지할 수 있으므로 파일을 올바르게 볼 수 name_*
있습니다 $1
.IFS
for
그러나 이제는 glob과 일치하는 파일의 총 개수를 얻는 간단한 방법이 필요합니다. for 루프에서 카운터를 사용할 수 있다는 것을 알고 있지만 파이프를 사용하여 이 작업을 수행할 수 있었으면 좋겠습니다 VAR
.
그러나 echo $VAR
글로빙을 성공적으로 수행했지만 다른 경로가 공백으로 연결되어 있으면 더 이상 항목을 분리할 수 없기 때문에 문제가 발생합니다... IFS 작동 방식과 같이 이 동작을 재정의할 수 있는 방법이 있습니까 for
?
답변1
원하는 것이 구분된 값의 목록인 경우 문자열 사용/확장을 피해야 합니다.
기본적인 해결책은 위치 매개변수를 설정하는 것입니다.
set -- "$1"/name_*
공백이나 개행 문자(또는 대부분의 다른 문자)가 있더라도 일치하는 각 파일을 별도의 위치 인수로 유지합니다.
shopt -s failglob
bash에서는 glob()이 어떤 파일과도 일치하지 않거나 glob이 어떤 파일과도 일치할 수 없고 어떤 결과도 얻고 싶지 않은 경우(그러나 glob 자체는 아님) 스크립트가 중지되도록 설정해야 합니다 . 스크립트가 중지되지 않도록 하려면 FAILGlob을 설정하지 않은 상태로 두세요.*
shopt -s nullglob
"$1"/name_*
파일 수(glob에 대한 일치 수를 계산합니다.) 이제 간단하게:
echo "$#"
위치 매개변수의 수입니다.
for 루프는 다음과 같이 줄어듭니다.
for file
do echo "$file"
done
이렇게 하면 완전히 분할되는 문제가 방지됩니다 IFS
.
$1
코드 삽입을 방지하려면 외부 값을 인용해야 합니다.
도 echo "$file"
인용되어야 한다.
배열에 목록을 할당하는 것도 가능합니다:
files=( "$1"/name_* )
이렇게 하면 위치 매개변수가 깨지는 것을 방지할 수 있지만 구문이 더 복잡해집니다. 배열의 요소 수는 다음과 같습니다.
echo "${#files[@]}"
루프에는 몇 가지 변경이 필요합니다.
for file in "${files[@]}"; do
echo "$file"
done
답변2
공간 문제를 해결할 수 있습니다.그리고배열 사용으로 전환하면 개수를 가져옵니다.
VAR=("$1/"name_*) # make array of filenames matching glob
echo "${#VAR[@]}" # number of elements in array
for file in "${VAR[@]}"; do # loop over individual elements of array
echo "$file"
grep ITEM "$file" -c # grep can count, wc isn't needed
done