흐름 제어와 함께 glob을 사용하는 방법은 무엇입니까?

흐름 제어와 함께 glob을 사용하는 방법은 무엇입니까?

디렉토리 목록(원하는 경우 폴더 목록)이 있습니다.

<something>.txt각 디렉토리에는 데이터베이스 덤프에서 생성된 이라는 파일이 있습니다 .

파일이 누락되면 명령이  실패하고 존중하여 디렉토리 위로 계속 이동하고 나머지 검사를 완료할 수 없기 때문에 파일이 존재하는 경우에만 진행하고 이름 <something>.txt을 바꾸는 cron 작업을 실행하고 싶습니다. "${PWD##*/}"_info.txt*.txtmvcd ..어느 것이 의도적입니까?아니요아래 코드 조각에 설명되어 있거나 표시되어 있습니다..

따라서 CONTEXT 코드는 다음과 같습니다.

f의 경우<디렉토리 목록>
하다
  CD "${f}"
  if [-e "*.txt"];       ← 질문 부분입니다
    mv *.txt "${PWD##*/}".txt ← 나머지는 단지 컨텍스트를 제공하는 것입니다.
  필리핀 제도
  CD..
완벽한

이 작은 클립에 대한 전문가 의견이 있나요?

이 예를 정리했습니다. 중요한 부분은 조건입니다:

[ -e "*.txt" ]

파일이 존재 하더라도 <something>.txt조건이 실패합니다 .

그것이 내가 묻는 것입니다.

답변1

한 가지 가능성은 glob에서 이러한 항목으로 배열을 생성한 다음 배열에 요소가 있는지 확인할 수 있는 것입니다. 예를 들어:

cur_opt=$(shopt -p nullglob) # get current status so we can restore
shopt -s nullglob # to let the glob expand to nothing
txt_files=( *txt )
$cur_opt # restore nullglob setting to what it was before
if [ ${#txt_files} -gt 0 ]; then
    ...
fi

파일에 대해 작업을 수행하려면 배열에 요소가 있는지 테스트하는 대신 배열을 반복할 수도 있습니다.

일치하는 항목이 있는지 정말로 확인하고 싶다면 compgen다음과 같은 것을 사용할 수 있습니다.

if [ ! -z "$(compgen -G "*.txt") ]; then
    ...
fi

이것은 단지 반환을 확인할 수도 compgen있으므로

if compgen -G "*.txt" &>/dev/null; then
    ...
fi

답변2

이 작은 영상에 대해 전문가들은 다음과 같이 말합니다.

  1. 디렉터리 목록과 여러 파일(미리 이름을 알 수 없는)을 처리하는 경우 f디렉터리 이름을 나타내는 데 를 사용하지 마세요. 정말 혼란스럽습니다.
  2. 단순히 수정 없이(예: ##, %또는 ) 쉘 변수 자체를(다른 것과 연결하지 않고) 처리하는 경우 중괄호가 필요하지 않습니다 :. /바라보다문제를 방지 하려면 언제 변수 주위에 큰따옴표를 추가해야 합니까 "${var}" ?

    따라서 나는 외부 루프가 다음과 같아야 한다고 제안합니다.

    d를 위해<디렉토리 목록>
    하다
        CD "$d"
        (각 디렉토리에서 실행되는 코드)
        CD..
    완벽한

@Eric Renouf의 완벽한 답변 외에도 작성하는 방법에는 여러 가지가 있습니다.(각 디렉토리에서 실행되는 코드). 다음은 시도한 것과 유사한 간단한 것입니다.

for f in *.txt
do
    if [ -e "$f" ]
    then
        mv -- "$f" "${PWD##*/}".txt
    fi
done

<something>.txt디렉토리에 파일이 하나만 있으면 원하는 대로 작동합니다. for f …루프는 $f파일 이름과 동일한 이름으로 한 번 실행되고 파일 이름이 변경됩니다. (나는 mv --이름이 다음으로 끝나는 것을 방지하기 위해 사용합니다.- 그렇지 않으면 옵션으로 해석됩니다.  현재 디렉터리의 파일이거나 상대 경로 이름 mv ./"$f" …이 확실하다면 안전할 수도 있습니다 . ) 디렉토리에 파일이 $f없으면 루프도 한 번 실행되며 (문자 그대로) 와 동일한 효과가 나타납니다 . 해당 이름의 파일이 없으므로 테스트가 실패하고 실행되지 않습니다.*.txt$f*.txt-emv

디렉터리에 텍스트 파일이 여러 개 있으면 문제가 발생할 수 있습니다. 만약 있다면N이렇게 파일을 저장하면 루프가 실행됩니다.N"${PWD##*/}".txt각 텍스트 파일의 이름은 .as 로 변경됩니다 .재커리 브래디는 다음과 같이 지적합니다., 이로 인해 마지막 파일이 첫 번째 파일을 덮어쓸 수 있습니다.N-1개 파일. 이 문제를 해결하는 한 가지 방법은 기존 파일을 덮어쓰려고 할 때 경고를 표시하고 승인 또는 거부 옵션이 제공되도록 명령 -i에 옵션을 추가하는 것입니다. mv물론 cron스크립트가 작업으로 실행되는 경우에는 아무 소용이 없습니다. 또 다른 방법은 break루프에 명령을 추가하는 것입니다.

*.txt의 f에 대해
하다
    if [-e "$f"]
    그 다음에
        mv -- "$f" "${PWD##*/}".txt
        나머지
    필리핀 제도
완벽한

이렇게 하면 루프가 한 번만 실행됩니다. 루프가 실행되면 break루프를 종료하는 명령이 실행되기 때문입니다. 이렇게 하면 첫 번째 텍스트 파일만 이름이 바뀌고 다른 파일은 유지됩니다. 파일이 여러 개 있다는 알림은 받지 않습니다.

약간 더 복잡한 접근 방식은 다중 파일 상황을 감지하고 처리하는 것입니다.

첫 번째 = 1
*.txt의 f에 대해
하다
    if [-e "$f"]
    그 다음에
        if["$first"]
        그 다음에
            mv -- "$f" "${PWD##*/}".txt
            첫 번째 =
        기타
            printf "경고: %s 파일의 이름이 바뀌지 않았습니다.\n" "$f"
        필리핀 제도
    필리핀 제도
완벽한

여기서 first플래그는 루프 시작 부분에 설정되고 첫 번째 반복 중에 지워지므로 후속 반복에서는 첫 번째가 아니라는 것을 알 수 있습니다. 또는 "${PWD##*/}".txt이미 존재하는지 확인할 수도 있습니다.

관련 정보