청소할 때 .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/
.bak
sources/*.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
로 확장하려고 시도합니다. backupfiles
bak 파일이 있으면 모든 파일 이름의 문자열이 됩니다. 파일이 없으면 문자열이 확장되지 않은 상태로 유지됩니다. 그런 다음 결과를 리터럴(확장되지 않음)과 비교하면 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