더 좋은 방법

더 좋은 방법

청소할 때 .bak 파일을 생성하는 간단한 코드가 있습니다. 다시 정리하면 bak 파일이 제거되고 .bak 파일이 없어집니다. bak "no .bak"를 표시해야 하지만 if 조건만 실행합니다. 코드는 다음과 같습니다.

#!/bin/bash
chmod u+x sources/*
if [ "$1" == "clean" ]
then

    if [ -f `sources/*.bak` ]
    then        
       rm sources/*.bak

    else
        echo "there's no .bak files"
    fi

elif ["" == "$1"]
then

echo "This script makes a backup for each .c or .h file in sources directory"

target_files=`echo -n $(ls sources/{*.c,*.h})`
echo
echo "Starting to backup: $target_files"

for i in $target_files 
do 
  cp "$i" "$i".bak
done

echo
echo "The following backup files were created: `echo -n $(ls sources/*.bak)`"
echo
echo "Done"

fi 

답변1

문제는 라인이다

if [ -f `sources/*.bak` ]

백틱은 `bash에서 특별한 의미를 갖습니다. 이는 명령을 평가하고 해당 출력을 반환하는 데 사용됩니다.

예를 들어, 사용자 이름이 다음과 같은 경우프로들그 다음에

if [ -f `whoami` ]

라는 존재가 있는지 확인합니다 frodl.

따라서 를 쓰면 sources/*.bak먼저 용어를 glob하려고 시도하지만 sources/*.bak디렉터리에 확장자를 가진 파일이 없기 때문에 용어가 확장되지 않습니다. 그런 다음 유효한 명령이 아닌 리터럴 용어를 실행하려고 시도합니다(실제로는sources/.baksources/*.bak할 수 있는(처음에 별표가 있는 파일 이름; shudder!)라는 파일이 있는데 sources/*.bak, 없는 것 같습니다. 그러나 이 파일에는 .bak이전에 제외했던 확장자가 있습니다 . )

파일이 있으면 sources/deletemyharddisk.bak용어가 sources/*.bak해당 문자열로 확장된 다음 실행을 시도합니다(하드 드라이브가 지워질 수도 있음).

따라서 해야 할 일은 일반적인 따옴표를 사용하는 것뿐입니다.

backupfiles=sources/*.bak
if [ "x${backupfiles}" = "xsources/*.bak" ]; then
     echo "no .bak files" 1>&2
else
     echo "there are .bak files"...
fi

먼저 용어를 변수 sources/*.bak로 확장하려고 시도합니다. backupfilesbak 파일이 있으면 모든 파일 이름의 문자열이 됩니다. 파일이 없으면 문자열이 확장되지 않은 상태로 유지됩니다. 그런 다음 결과를 리터럴(확장되지 않음)과 비교하면 sources/*.bak일치하는 파일이 있기 때문에 확장이 발생했는지 여부를 알 수 있습니다.

더 좋은 방법

하지만 먼저 파일이 있는지 확인한 후 삭제할 이유는 없습니다. 더 간단한 접근 방식은 특정 패턴과 일치하는 모든 파일을 삭제하는 것입니다. find당신을 위해 이것을 할 수 있습니다:

find sources/ -maxdepth 1 -type f -name "*.bak" -delete

-maxdepth 1(이렇게 하면 디렉터리( ) 의 첫 번째 수준에서 sources/( )로 끝나는 파일을 검색합니다( -type f; 디렉터리나 심볼릭 링크 등이 아님). 그런 다음 해당 파일을 삭제합니다( )..bak-name "*.bak"-delete

파싱되지 않음ls

코드의 또 다른 문제는

target_files=`echo -n $(ls sources/{*.c,*.h})`
for i in $target_files 
...

당신은해야구문 분석되지 않은 출력ls.

대신 다음과 같은 것을 사용하십시오.

 for i in sources/*.c sources/*h
 do
   #...
 done

관련 정보