>

$sh backup-to-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'의 출력을 구문 분석해서는 안됩니다!

    Shell의 파일 이름과 경로 이름 : 올바르게 수행하는 방법!

    예를 들어 파일 중 파일 이름에 '-'(대시/하이픈)이 있으면 이스케이프되지 않은 파일 (백 슬래시 ( '\'))이 매개 변수로 해석 될 수 있습니다.

    '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* =
    
    

    이것에는 몇 가지 문제가 있습니다. 먼저, 쉘 스크립팅에서 일치 패턴을 "글로브"할 수 없습니다. 글쎄, 할 수 있지만, fileglob가 둘 이상의 일치하는 결과를 가져 오면 둘 다 얻을 수 있으며,이 경우 "["프로그램 (예, 프로그램)은 다음을 평가하려고 시도합니다.

    filename1 filename2 filename3 = $i
    
    

    fileglob이 정확히 하나의 파일 이름으로 확장되는 경우에만 작동하며 거의 보장 할 수 없습니다. 귀하의 경우 $filename은 하나 이상의 파일로 확장되지만 항상 그런 것은 아닙니다. "$file *"이 전혀 파일로 확장되지 않으면 (쇼핑 설정에 따라) 빈 문자열을 얻을 수 있습니다 :

    = $i
    
    
    [ 를 일으킬 것입니다

     실패. 그러나 올바른 쇼핑을하면 다음과 같은 이점이 있습니다.

    backup-2014-whatever* = $i
    
    
    * 와 함께  비교의 일부입니다.

    두 번째 근본적인 문제는 -F 의 사용입니다   ls 의 매개 변수 . 파일이 실행 파일인지, 소프트 링크인지에 따라 ls가 파일 이름에 여러 문자 중 하나를 추가하도록 지시합니다.

    NetScr1be는 무언가에 있지만 NetScr1be의 조언을 따를 필요가 없으며 ls 를 사용하지 않아도됩니다. ... 그냥 ls -l 를 사용하지 마십시오 . 대신 ls -1 를 사용하십시오.  단 하나의 열로 파일 이름 만 인쇄하고 프릴은 없습니다. (매우 큰 디렉토리의 경우 디렉토리를 정렬하므로 정렬되지 않은 옵션이 있거나 찾기를 사용하는 경우 문제가 될 수 있습니다.)

    보다 안전하려면 - 로 시작하는 이상한 파일 이름을 확인하기 위해 변수를 큰 따옴표로 묶고 LHS와 RHS에 더미 문자를 접두어로 붙여야합니다.  버리지 마십시오.

    글렌의 조언을 어느 정도 사용하고 다음과 같이하겠습니다 :

    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

관련 자료

  • 이전 Shell script - 쉘 스크립트 - 이 'if'에 대해 'fi'를 찾을 수 없습니다
  • 다음 subversion - SVN 변경 내 모든 체크 아웃