나는 이것이 간단 할 것이라고 생각했지만 예상보다 더 복잡하다는 것이 증명되었습니다.
디렉토리에서 특정 유형의 모든 파일을 반복하고 싶으므로 다음과 같이 작성합니다.
#!/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
어떻게 작성합니까? 일치하는 파일을 깔끔하게 처리하는 루프?
댓글
답변
bash
에서 nullglob
옵션을 설정할 수 있습니다. 리터럴 문자열로 처리되지 않고 “사라진”항목과 일치하지 않습니다.
shopt -s nullglob for fname in *.zip ; do echo "current file is ${fname}" done
POSIX 쉘 스크립트에서 fname
가 존재합니다 (그리고 동시에 [ -f ]
와 함께 디렉토리 / fifo / device와 같은 다른 유형이 아닌 일반 파일 (또는 일반 파일에 대한 심볼릭 링크)인지 확인하십시오 .. .) :
for fname in *.zip; do [ -f "$fname" ] || continue printf "%s\n" "current file is $fname" done
다음의 경우 [ -f "$fname" ]
를 [ -e "$fname" ] || [ -L "$fname ]
로 바꿉니다. 이름이 .zip
로 끝나는 모든 (숨겨지지 않은) 파일을 반복하고 싶습니다. 해당 유형.
이름이 iv로 끝나는 숨겨진 파일도 고려하려면 *.zip
를 .*.zip .zip *.zip
로 바꿉니다. id = “2befeeca63″>
.
댓글
-
shopt -s nullglob
가 작동하지 않았습니다. 우분투 17.04에서 저를 사용했지만[ -f "$fname" ] || continue
는 잘 작동했습니다. - @koppor 실제로 사용하지 않는 것 같습니다. '
bash
. - POSIX 솔루션의 경우 +1.
답변
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 *
Answer
찾기 사용
export -f myshellfunc find . -mindepth 1 -maxdepth 1 -type f -name "*.zip" -exec bash -c "myshellfunc "$0"" {} \;
export -f
이 작동합니다. 이제 find
는 셸 함수를 실행하는 bash
를 실행하고 현재 dir 수준 만 유지합니다.
댓글
- 하위 디렉토리를 통해 반복되며 일치에 대해 bash 함수 (스크립트 아님)를 호출하려고합니다.
- @symcbean I ' 단일 디렉토리로 제한하고 bash 기능을 처리하도록 수정했습니다.
답변
대신 of :
FILES=`ls *.zip`
시도 :
FILES=`ls * | grep *.zip`
이 방법으로 ls가 실패하면 귀하의 경우) 실패한 출력을 grep하고 빈 변수로 반환합니다.
current file is <---Blank Here
여기에 로직을 추가하여 “아니오”를 반환 할 수 있습니다. File Found “
#!/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 값으로 종료) 현재 파일을 인쇄하고 그렇지 않으면”No 찾은 파일 “
댓글
- 더 나은 도구 (
find
)를 사용하여 문제를 해결하는 것보다 프로세스 (grep
)를 하나 더 추가하는 것은 좋지 않습니다. ) 또는 현재 솔루션에 대한 관련 설정 변경 (shopt -s nullglob
사용) - OP '의 설명에 따라 원래 게시물에서는
shopt -s nullglob
가 작동하지 않습니다. 내 답변을 확인하는 동안find
를 시도했지만 계속 실패했습니다. Dani가 말한 수출 때문이라고 생각합니다.
shopt -s nullglob
를 추가하세요.FILES=
ls * .zip; for fname in "${FILES}"...
그러나for fname in *.zip ; do....
에서는 예상대로 작동합니다.`ls ...`
가 아닙니다. @cuonglm '의 제안은 패턴이 없을 때*.zip
가 아무것도 확장되지 않도록하는 것입니다. ' t 모든 파일과 일치합니다.ls
인수없이 현재 디렉토리를 나열합니다.ls
의 출력을 일반적으로 구문 분석하는 이유를 설명합니다. 피함 : 왜ls
를 구문 분석하지 않습니까 ? ; 해당 페이지 상단에있는 BashGuide '의 ParsingLs 문서 링크도 참조하세요.