저는 이것이 간단하다고 생각했습니다. 그러나 알고 보니 제가 예상했던 것보다 더 복잡했습니다.
디렉토리에 있는 특정 유형의 모든 파일을 반복하고 싶기 때문에 다음과 같이 작성합니다.
#!/bin/bash
for fname in *.zip ; do
echo current file is ${fname}
done
이게 효과가 있어일치하는 파일이 하나 이상 있는 경우디렉토리에. 그러나 일치하는 파일이 없으면 다음과 같은 결과가 나타납니다.
current file is *.zip
그런 다음 다음을 시도합니다.
#!/bin/bash
FILES=`ls *.zip`
for fname in "${FILES}" ; do
echo current file is ${fname}
done
파일이 없으면 루프 본문이 실행되지 않지만 ls에서 오류가 발생합니다.
ls: *.zip: No such file or directory
일치하지 않는 파일을 깔끔하게 처리하기 위해 루프를 어떻게 작성할 수 있습니까?
답변1
에서는 어떤 것과도 일치하지 않는 패턴이 리터럴 문자열로 처리되는 대신 "사라지도록" 옵션을 bash
설정할 수 있습니다 .nullglob
shopt -s nullglob
for fname in *.zip ; do
echo "current file is ${fname}"
done
POSIX 쉘 스크립트에서는 그것이 fname
존재하는지 확인할 수 있습니다(또한 를 사용하여 [ -f ]
/fifo/devices... 디렉토리와 같은 다른 유형이 아닌 일반 파일(또는 일반 파일에 대한 심볼릭 링크)인지 확인하십시오):
for fname in *.zip; do
[ -f "$fname" ] || continue
printf '%s\n' "current file is $fname"
done
이름이 임의 유형으로 끝나는 모든(숨겨지지 않은) 파일을 반복하려면 [ -f "$fname" ]
로 바꾸십시오.[ -e "$fname" ] || [ -L "$fname ]
.zip
로 끝나는 이름도 고려하고 싶다면 *.zip
..*.zip .zip *.zip
.zip
답변2
set ./* #set the arg array to glob results
${2+":"} [ -e "$1" ] && #if more than one result skip the stat "$1"
printf "current file is %s\n" "$@" #print the whole array at once
###or###
${2+":"} [ -e "$1" ] && #same kind of test
for fname #iterate singly on $fname var for array
do printf "file is %s\n" "$fname" #print each $fname for each iteration
done
여기 댓글에서 함수 호출을 언급하셨는데요...
file_fn()
if [ -e "$1" ] || #check if first argument exists
[ -L "$1" ] #or else if it is at least a broken link
then for f #if so iterate on "$f"
do : something w/ "$f"
done
else command <"${1-/dev/null}" #only fail w/ error if at least one arg
fi
file_fn *
답변3
찾기 사용
export -f myshellfunc
find . -mindepth 1 -maxdepth 1 -type f -name '*.zip' -exec bash -c 'myshellfunc "$0"' {} \;
export -f
이 작업을 수행 하려면 셸 기능을 내보내야 합니다 . 이제 find
실행하면 bash
셸 기능이 실행되고 현재 디렉터리 수준에만 유지됩니다.
답변4
바꾸다:
FILES=`ls *.zip`
노력하다:
FILES=`ls * | grep *.zip`
이렇게 하면 ls가 실패하면(귀하의 경우) 실패 출력을 파악하여 빈 변수로 반환합니다.
current file is <---Blank Here
"파일을 찾을 수 없음"을 반환하도록 몇 가지 논리를 추가할 수 있습니다.
#!/bin/bash
FILES=`ls * | grep *.zip`
if [[ $? == "0" ]]; then
for fname in "$FILES" ; do
echo current file is $fname
done
else
echo "No Files Found"
fi
이렇게 하면 이전 명령이 성공하면(값 0으로 종료) 현재 파일이 인쇄되고, 그렇지 않으면 "파일을 찾을 수 없음"이 인쇄됩니다.