bash iterate file list, except when empty

나는 이것이 간단 할 것이라고 생각했지만 예상보다 더 복잡하다는 것이 증명되었습니다.

디렉토리에서 특정 유형의 모든 파일을 반복하고 싶으므로 다음과 같이 작성합니다.

#!/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가 말한 수출 때문이라고 생각합니다.

답글 남기기

이메일 주소를 발행하지 않을 것입니다. 필수 항목은 *(으)로 표시합니다