Development Tip

rm은 스크립트에서 와일드 카드로 파일을 삭제하지 못하지만 쉘 프롬프트에서 작동합니다.

yourdevel 2021. 1. 10. 19:38
반응형

rm은 스크립트에서 와일드 카드로 파일을 삭제하지 못하지만 쉘 프롬프트에서 작동합니다.


Linux 쉘 스크립트에서 정말 어리석은 문제에 봉착했습니다. 디렉토리에서 확장자가 ".bz2"인 모든 파일을 삭제하고 싶습니다. 내가 부르는 스크립트에서

rm "$archivedir/*.bz2"

여기서 $ archivedir은 디렉토리 경로입니다. 아주 간단해야하지 않나요? 어떻게 든 다음 오류로 실패합니다.

rm: cannot remove `/var/archives/monthly/April/*.bz2': No such file or directory

그러나이 있다 디렉토리라는 test.bz2의 파일 내가 내 스크립트를 변경하는 경우

echo rm "$archivedir/*.bz2"

해당 행의 출력을 터미널 창에 복사 / 붙여 넣기하면 파일이 성공적으로 제거됩니다. 내가 도대체 ​​뭘 잘못하고있는 겁니까?


TL; DR

와일드 카드를 사용하여 예상되는 전체 경로가 아닌 변수 만 인용하십시오.

rm "$archivedir"/*.bz2

설명

  • Unix에서 프로그램은 일반적으로 와일드 카드 자체를 해석하지 않습니다. 쉘은 인용되지 않은 와일드 카드를 해석하고 각 와일드 카드 인수를 일치하는 파일 이름 목록으로 바꿉니다. $ archivedir에 공백이 포함되어 있으면 rm $archivedir/*.bz2수행하지 않을 수 있습니다.

  • 와일드 카드 문자를 인용하거나 큰 따옴표 또는 작은 따옴표를 사용하거나 그 앞에 백 슬래시를 사용하여이 프로세스를 비활성화 할 수 있습니다. 그러나 이것은 여기서 원하는 것이 아닙니다. 와일드 카드가 일치하는 파일 목록으로 확장되기를 원합니다.

  • rm $archivedir/*.bz2(따옴표없이) 쓰기에주의하십시오 . 단어 분할 (즉, 명령 줄을 인수로 나누는 것) 은 $ archivedir이 대체 된 후에 발생합니다 . 따라서 $ archivedir에 공백이 포함되어 있으면 의도하지 않은 추가 인수가 표시됩니다. archivedir은 /var/archives/monthly/April to June입니다. 그런 다음 rm /var/archives/monthly/April to June/*.bz2"/ var / archives / monthly / April", "to"파일 및 "June / *. bz2"와 일치하는 모든 파일을 삭제하려고하는 쓰기와 동일한 결과를 얻을 수 있습니다. .

올바른 해결책은 다음과 같이 작성하는 것입니다.

rm "$ archivedir"/ *. bz2

당신의 원래 라인

rm "$archivedir/*.bz2"

다음과 같이 다시 작성할 수 있습니다.

rm "$archivedir"/*.bz2

동일한 효과를 얻을 수 있습니다. 기존 설정에서 와일드 카드 확장이 제대로 수행되지 않습니다. 큰 따옴표를 파일 경로의 "앞"(적법한)으로 이동하면이를 방지 할 수 있습니다.


이것을 조금 확장하기 위해 bash는 따옴표로 묶인 메타 문자를 처리하는 데 상당히 복잡한 규칙을 가지고 있습니다. 일반적으로

  • 작은 따옴표로 해석되는 것은 거의 없습니다.

     echo '$foo/*.c'                  => $foo/*.c
     echo '\\*'                       => \\*
    
  • 셸 대체는 큰 따옴표 안에 이루어 지지만 파일 메타 문자는 확장되지 않습니다.

     FOO=hello; echo "$foo/*.c"       => hello/*.c
    
  • 역 따옴표 안의 모든 것은 그것들을 해석하는 서브 쉘로 전달됩니다. 내 보내지 않은 셸 변수는 하위 셸에 정의되지 않습니다. 따라서 첫 번째 명령은 공백으로 에코되지만 두 번째 및 세 번째 명령은 "bye"를 에코합니다.

    BAR=bye echo `echo $BAR`
    BAR=bye; echo `echo $BAR`
    export BAR=bye; echo `echo $BAR`
    

(그리고 이것을 원하는 방식으로 인쇄하는 것은 여러 번 시도하는 것이 분명히 불가능합니다 ...)


따옴표로 인해 문자열이 문자열 리터럴로 해석됩니다. 제거해보십시오.


다른 셸 스크립트에서 ./shell_script.sh 와 같은 셸 스크립트를 호출 할 때 비슷한 오류가 발생했습니다 . sh shell_script.sh 로 호출하여 수정할 수 있습니다.


왜 안돼 rm -rf */*.bz2? OSX에서 나를 위해 작동합니다.

참조 URL : https://stackoverflow.com/questions/790195/rm-fails-to-delete-files-by-wildcard-from-a-script-but-works-from-a-shell-promp

반응형