3

この作業は、テスト用の virtualbox マシンで行われています

/root ディレクトリに、
「/root/foo」
「/root/bar」
「/root/i have multiple words」を作成しました。

ここに私が現在持っている(関連する)コードがあります

  if [ ! -z "$BACKUP_EXCLUDE_LIST" ]
  then
    TEMPIFS=$IFS
    IFS=:
    for dir in $BACKUP_EXCLUDE_LIST
    do
      if [ -e "$3/$dir" ] # $3 is the backup source
      then
          BACKUP_EXCLUDE_PARAMS="$BACKUP_EXCLUDE_PARAMS --exclude='$dir'"
      fi    
    done
    IFS=$TEMPIFS
  fi


  tar $BACKUP_EXCLUDE_PARAMS -cpzf  $BACKUP_PATH/$BACKUP_BASENAME.tar.gz -C $BACKUP_SOURCE_DIR $BACKUP_SOURCE_TARGET

これは、スクリプトを sh -x で実行するとどうなるかです

+ IFS=:
+ [ -e /root/foo ]
+ BACKUP_EXCLUDE_PARAMS= --exclude='foo'
+ [ -e /root/bar ]
+ BACKUP_EXCLUDE_PARAMS= --exclude='foo' --exclude='bar'
+ [ -e /root/i have multiple words ]
+ BACKUP_EXCLUDE_PARAMS= --exclude='foo' --exclude='bar' --exclude='i have multiple words'
+ IFS=  

# So far so good

+ tar --exclude='foo' --exclude='bar' --exclude='i have multiple words' -cpzf /backup/root/daily/root_20130131.071056.tar.gz -C / root
tar: have: Cannot stat: No such file or directory
tar: multiple: Cannot stat: No such file or directory
tar: words': Cannot stat: No such file or directory
tar: Exiting with failure status due to previous errors

# WHY? :(

チェックは正常に完了しますが、--exclude='i have multiple words'機能しません。

手動でシェルに入力すると機能することに注意してください。

tar --exclude='i have multiple words' -cf /somefile.tar.gz /root

配列を使用する場合、これが bash で機能することはわかっていますが、これを POSIX にしたいと考えています。

これに対する解決策はありますか?

4

2 に答える 2

1

このスクリプトを検討してください。('with whitespace' と 'example.desktop' はサンプルファイルです)

#!/bin/bash

arr=("with whitespace" "examples.desktop")

for file in ${arr[@]}
do
    ls $file
done

これはあなたのものとまったく同じように出力されます。

21:06 ~ $ bash test.sh 
 ls: cannot access with: No such file or directory
 ls: cannot access whitespace: No such file or directory
 examples.desktop

IFS を '\n' 文字に設定して、ファイル名の空白をエスケープできます。

#!/bin/bash

arr=("with whitespace" "examples.desktop")

(IFS=$'\n';
    for file in ${arr[@]}
    do
        ls $file
    done
)

2 番目のバージョンの出力は次のようになります。

21:06 ~ $ bash test.sh 
 with whitespace
 examples.desktop
于 2013-01-31T19:32:48.313 に答える
0

LinuxQuestions フォーラムの David the H. が私を正しい方向に導いてくれました。

まず第一に、私の質問では、私は IFS=: を tar コマンドまでずっと使用しませんでした。第二に、安全のために「set -f」を含めました。

BACKUP_EXCLUDE_LIST="foo:bar:i have multiple words"

# Grouping our parameters
if [ ! -z "$BACKUP_EXCLUDE_LIST" ]
then
  IFS=:         # Here we set our temp $IFS
  set -f        # Disable globbing
  for dir in $BACKUP_EXCLUDE_LIST
  do
    if [ -e "$3/$dir" ]  # $3 is the directory that contains the directories defined in $BACKUP_EXCLUDE_LIST
    then
      BACKUP_EXCLUDE_PARAMS="$BACKUP_EXCLUDE_PARAMS:--exclude=$dir"
    fi    
  done
fi

# We are ready to tar

tar $BACKUP_EXCLUDE_PARAMS \
  -cpzf  "$BACKUP_PATH/$BACKUP_BASENAME.tar.gz" \
  -C "$BACKUP_SOURCE_DIR" \
  "$BACKUP_SOURCE_TARGET"
unset IFS       # our custom IFS has done it's job. Let's unset it!
set +f          # Globbing is back on

私が行ったように、TEMPIFS 変数を使用しないことをお勧めします。その方法では IFS が正しく設定されないためです。作業が完了したら、IFS の設定を解除することをお勧めします

于 2013-02-01T19:37:10.177 に答える