$ sh s3.sh에 백업
backup-to-s3.sh: 11: [: bkup_20151106_150532.zip: unexpected operator
backup-to-s3.sh: 11: [: bkup_20151106_150532.zip: unexpected operator
backup-to-s3.sh: 11: [: bkup_20151106_150532.zip: unexpected operator
backup-to-s3.sh: 11: [: bkup_20151106_150532.zip: unexpected operator
backup-to-s3.sh: 11: [: bkup_20151106_150532.zip: unexpected operator
backup-to-s3.sh: 11: [: bkup_20151106_150532.zip: unexpected operator
ubuntu@accretive-staging-32gb-ephemeral:~$ cat backup-to-s3.sh
#Script to move /home/ubuntu/backup folder to S3://auto-backup
#Author Ashish Karpe
cd /mnt/backup
filename="bkup_$(date +%Y%m%d_)"
/bin/ls -alF | awk '{ print $9 }' > /tmp/file
for i in $(cat /tmp/file); do
# echo $i;
# read a;
# echo $filename;
if [ $filename* = $i ]
then
echo "Copying " $i "to S3://auto-backup";
s3cmd put $i s3://auto-backup
fi
done
답변1
for
파일의 행을 반복하는 데 사용하지 말고 다음을 사용하십시오.while IFS= read -r line; do ...; done < filename
ls
출력을 파일로 파이프 할 필요가 전혀 없습니다 .특히사용-F
- bash 를 사용한
[[ x == y ]]
패턴 비교 , 오른쪽 패턴:
#!/bin/bash
cd /mnt/backup
prefix="bkup_$(date +%Y%m%d_)"
for file in * .*; do
[[ -f $file ]] || continue # skip things like directories and soft links
if [[ $file == $prefix* ]]; then
echo "Copying " $file "to S3://auto-backup";
s3cmd put $file s3://auto-backup
fi
done < /tmp/file
답변2
"ls"의 출력을 파일에 덤프하고 구문 분석하더라도 "ls"의 출력을 간접적으로 구문 분석하는 것입니다. 이는 문제가 있거나 매우 나쁜 생각이거나 완전히 잘못된 것입니다! 누구에게 물어보느냐에 따라 다릅니다.
이것은셸의 파일 이름과 경로 이름: 올바르게 얻는 방법!
예를 들어, 파일 이름에 "-"(대시/하이픈)이 있고 이스케이프 처리되지 않은 경우(앞에 백슬래시("\")를 추가하여) 매개변수로 해석될 수 있습니다.
"ls" 구문 분석을 피하는 것은 다음과 같이 간단할 수 있습니다.
find . -maxdepth 1 -iname "*"
.
./dont_parse_ls.sh
./array.dat
./.bashrc
./BASH.Indirect.Reference.sh
./basharray.sh
./.forever
결과는 같습니다
/bin/ls -alF | awk '{ print $9 }'
./
../
.bashrc
.forever/
BASH.Indirect.Reference.sh
array.dat
basharray.sh*
dont_parse_ls.sh
청소년MMV
답변3
스크립트에는 적어도 두 가지 주요 문제가 있습니다. 근본적인 문제는 조각입니다.
if [ $filename* =
여기에는 몇 가지 문제가 있습니다. 첫째, 쉘 스크립트에서는 일치하는 패턴을 "와일드카드"로 지정할 수 없습니다. 글쎄, 할 수는 있지만 fileglob이 여러 일치 항목을 생성하는 경우 동시에 모두 얻을 수 있으며, 이 경우 "[" 프로그램(예, 프로그램입니다)은 다음을 평가하려고 시도합니다.
filename1 filename2 filename3 = $i
fileglob이 정확히 파일 이름으로 확장되는 경우에만 작동하지만 이를 보장할 수는 없습니다. 귀하의 경우 $filename은 최소한 하나의 파일로 확장되지만 항상 그런 것은 아니라는 점에 유의해야 합니다. "$file*"이 파일이 전혀 없는 것으로 확장되면 (shopt 설정에 따라) 빈 문자열을 얻을 수 있습니다.
= $i
이로 인해 [
고장이 발생합니다. 그러나 올바른 매장을 이용하면 다음과 같은 이점을 얻을 수 있습니다.
backup-2014-whatever* = $i
*
비교의 일환 으로 .
두 번째 기본 문제는 -F
매개변수의 사용 입니다 ls
. 이는 파일이 실행 파일인지, 소프트 링크인지 등에 따라 파일 이름에 여러 문자 중 하나를 추가하도록 ls에 지시합니다.
NetScr1be는 의미가 있지만 NetScr1be의 조언을 따를 필요는 없으며 절대로 사용하지 마십시오 ls
. 그냥 사용하지 마십시오 ls -l
. 대신, ls -1
이를 사용하면 파일 이름이 아무런 장식 없이 단일 열에 인쇄됩니다. (매우 큰 디렉토리의 경우 정렬하므로 문제가 될 수 있습니다. 이 경우 정렬이 없는 옵션이 있습니다. 대안으로 find를 사용하십시오.)
보다 안전하려면 변수를 큰따옴표로 묶어야 하며 LHS와 RHS 모두 앞에 더미 문자를 붙여서 a로 시작하는 이상한 파일 이름이 -
손실되지 않도록 해야 합니다.
나는 Glenn의 조언을 어느 정도 받아들여 이렇게 할 것입니다.
command ls -1 | while read file; do
if [ x"$file" = x"$filename" ]]; then
echo Do Work Here
fi
done
나는 이렇다회의그런데 글렌이 친절하게도 꼭 해야 한다고 말했어요그의방법:
for file in *; do
if [[ $file == $filename ]]; then ...
답변4
이 스크립트가 모든 작업을 수행합니다. 왜 안되나요? 쉘이 올바른 파일을 선택하므로 다음을 호출할 필요가 없습니다 ls
.
#!/bin/sh
for file in /mnt/backup/bkup_$(date +%Y%m%d)_*
do
s3cmd put "$file" s3://auto-backup
done
- 유일한 외부 명령은 입니다
s3cmd
. - 성명 이 없습니다
if
. - 유일한 결정 지점은
for
루프입니다. - 읽기 쉬운.