YMMV

YMMV

$ 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

  1. for파일 줄을 반복하는 데 사용하지 말고

    while IFS= read -r line; do ...; done < filename
    
  2. ls출력을 파일로 파이프할 필요가 전혀 없습니다 .특히사용하여-F

  3. 패턴 비교를 위해 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'의 출력을 구문 분석하면 안되는 이유!

여기는셸의 파일 이름 및 경로 이름: 올바르게 수행하는 방법!

예를 들어, 파일 이름에 이스케이프되지 않은 '-'(대시/하이픈)이 있는 경우(백슬래시('\')를 접두사로 지정) 매개변수로 해석될 수 있습니다.

'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루프입니다.
  • 읽기 쉬운.

관련 정보