"rm *" 실행 시 "일치하는 항목 없음"을 제거하는 방법

"rm *" 실행 시 "일치하는 항목 없음"을 제거하는 방법

를 사용하여 zsh맞지 않는 패턴을 선택하면 rm출력이 리디렉션되더라도 "일치 항목을 찾을 수 없습니다"라는 메시지가 나타납니다.

# rm * > /dev/zero 2>&1
  zsh: no matches found: *

이 메시지를 어떻게 없앨 수 있나요?

답변1

이 동작은 여러 요소에 의해 제어됩니다.Zsh의 와일드카드 옵션. 기본적으로 명령줄에 일치하지 않는 와일드카드 표현식이 포함되어 있으면 Zsh는 표시되는 오류 메시지를 인쇄하고 명령을 전혀 실행하지 않습니다. 다음 세 가지 방법으로 이 기능을 비활성화할 수 있습니다.

  • setopt +o nomatch

    아무것도 일치하지 않는 와일드카드 표현식이 남게 되며 오류 메시지가 표시됩니다 rm( 를 사용하여 비활성화할 수 있지만 -f원하지 않는 경우 강제로 제거하게 되므로 좋지 않습니다).

  • setopt +o nullglob

    어떤 것과도 일치하지 않는 패턴은 제거됩니다(따라서 효과적으로 무시됩니다).

  • setopt +o cshnullglob

    아무것도 일치하지 않는 패턴은 제거되며, 명령의 모든 패턴이 제거되면 오류가 보고됩니다.

마지막 두 개는 다룹니다 nomatch. 이러한 옵션은 모두 설정을 해제하여 설정할 수 있습니다 setopt -o ….

nullglob단일 모드는 다음을 사용하여 활성화할 수 있습니다.글로벌 N예선,예를 들어:

rm -f -- *(N)

답변2

무엇을 하길 원하시나요? rm(1) 전혀 실행되지 않습니까? *Bourne과 유사한 다른 쉘처럼 문자 그대로의 인수를 사용하여 실행하시겠습니까(2)? 아무런 인수 없이 실행하시겠습니까(3)?

  1. files=(*(N)); (($#files)) && rm -- $files. 또는 (rm -- *) 2> /dev/null그렇게 하면 실제 오류도 숨겨지는데, rm이는 어리석은 일입니다. 오류를 삭제할 수 있지만 명령 zsh의 stderr을 복원할 수 있습니다.rm(rm -- * 2>&3 3>&-) 3>&2 2> /dev/null
  2. emulate sh -c 'rm -- *' 2> /dev/null. 그런 다음 해당 단일 명령줄에 대해 시뮬레이션된 sh것처럼 zsh불일치가 *있는 그대로 전달되고 rm파일 이 존재하지 않는다고 rm불평합니다 . *우리는 오류 메시지를 억제한 rm것처럼 stderr를 억제합니다 sh. 하지만 이는 텍스트를 전달하는 잘못된 행동으로 인해 발생하는 오류 rm가 아니라 실제 오류를 숨기기 때문에 어리석은 일입니다 . 그러나 존재하지 않는 파일 에 대해 불평하지 않으므로 다음을 수행할 수 있습니다.sh*rmrm -f '*'*emulate sh -c 'rm -f -- *'
  3. rm -- *(N). rm매개 변수가 전달되지 않으면 불평하지만 다시는 그렇지 않습니다 rm -f.rm -f -- *(N)

일반적으로 말하면 rm -f모든 파일을 없애고 rm파일을 삭제할 수 없거나 반환 후에도 IOW가 여전히 존재하는 경우에만 오류가 발생하는 경우 이 명령을 사용해야 합니다. 또한 -f특정 상황에서 사용자에게 메시지가 표시되지 않도록 일반적으로 스크립트에서 이를 사용 하려고 합니다 .

여기서 rmglob이 일치하지 않을 때 호출하는 것은 오류입니다. 1 행동이 잘못되었습니다. 이와 같은 패턴의 경우 이는 무해하지만, 이와 같은 패턴의 경우 일치 sh하지 않을 때 그대로 전달하면 파일이 잘못 삭제될 수 있습니다.**.[ch]*.[ch]*.[ch]

$ ls
*.[ch]  foo.txt
$ zsh -c 'rm *.[ch]'
zsh:1: no matches found: *.[ch]
$ ls
*.[ch]  foo.txt
$ sh -c 'rm *.[ch]'
$ ls
foo.txt

오류로 인해 실패하는 것이 가장 현명한 일이며, 그것이 ( , , 및 원래 Unix 셸 zsh도 마찬가지입니다 ) 하는 일입니다.fishcshtcshbash -o failglob

이 특정 사례를 직접 처리하려면 zsh다음을 사용하여 쉽게 처리할 수 있습니다.(N) 글로벌 예선(을 위한빈 공) 위의 (1)의 경우와 같습니다. fish(적어도최신 버전) 하나의 글로벌이기 때문에 더 쉽습니다.빈 공명령 set(변수를 할당하는 명령)의 매개변수에 있을 때의 패션입니다. 따라서 동등한 상황은 다음과 같습니다.

set files *
if count $files > /dev/null
  rm -f -- $files
end

바라보다nullglob이 기본값이 아닌 이유자세한 내용은.


1.sh 엄밀히 말하면 Bourne 쉘(1979년 Unix V7 이후)부터 적용 되었습니다 sh./etc/glob전반적인 상황name is from )은 cshor 처럼 동작합니다 zsh -o cshnullglob. 즉, /etc/glob일치하는 glob이 없으면 명령이 중단됩니다(그리고 하나 이상의 glob이 일치하는 경우 일치하지 않는 glob은 억제됩니다). 행동은부서진Bourne 쉘을 통해.

답변3

대화형 zsh에서 다음을 입력합니다.

setopt no_nomatch
rm * > /dev/null 2>&1
setopt nomatch  # `nomatch` is default, see `man zshoptions`

나에게는 작동 nullglob하지 않습니다cshnullglob

답변4

평판이 부족해서 댓글을 달 수 없습니다. Stephen Kitt의 답변에 추가하려면 옵션을 작동시키기 위해 setopt대신 사용해야 했습니다 . setopt +ozsh 5.9를 사용하고 있습니다.

setopt nullglob
declare -a files=(${SOME_PATH}/*.log)

for f in "${files[@]}"; do
    printf "Removing ${f}...\n"
    rm -f "${f}" || printf "Failed to remove ${f}\n"
done

일치하는 항목이 없으면 files배열이 비어 있고 루프가 입력되지 않으므로 내 요구 사항을 완벽하게 충족합니다.

관련 정보