
$ 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
YMMV
답변3
스크립트에는 적어도 2가지 주요 문제가 있습니다. 근본적인 문제는 스니펫입니다.
if [ $filename* =
여기에는 몇 가지 문제가 있습니다. 첫째, 쉘 스크립팅에서는 일치 패턴을 "glob"할 수 없습니다. 글쎄, 그렇게 할 수는 있지만, fileglob이 둘 이상의 일치 항목을 찾으면 두 항목 모두를 얻게 되며, 이 경우 "[" 프로그램(예, 프로그램입니다)은 다음을 평가하려고 시도합니다.
filename1 filename2 filename3 = $i
이는 파일글롭이 정확히 하나의 파일 이름으로 확장되는 경우에만 작동하며 이를 보장할 수 있는 경우는 거의 없습니다. 귀하의 경우 $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
루프입니다. - 읽기 쉬운.