1

スペースを含むいくつかの Windows パスを使用する Bash スクリプト (Cygwin) があります。\その結果、変数定義で a を使用してスペースをエスケープしました。

スクリプト内のすべてが正常に機能します。ただし、この変数を引数としてコマンドライン実行可能ファイルに渡す必要があります。そうなると、逃げ道がめちゃくちゃになる。

機能しないスクリプトの例:

#!/bin/sh

# File paths
destinationPath="/cygdrive/c/Documents and Settings/Eric/My Documents/"
attachments="\n2013-12-12.pdf"
body="Test Body"
recipient="asdf@asdf.com"


# Prepare attachments
args=""
for file in $attachments ; do
    file=${file//[ \\n]/}
    touch $file
    mv $file "$destinationPath/$file"
    args="$args -a $destinationPath/$file"
done


# Send email
echo -e $body | email --from-addr nosender@mydomain.com --from-name "Automated CSS Downloader" --subject "Downloaded new file(s) \
  from CSS" $args eric@mydomain.com

スクリプトからの出力:

$ bash -x test.sh
+ destinationPath='/cygdrive/c/Documents and Settings/Eric/My Documents/'
+ attachments='\n2013-12-12.pdf'
+ body='Test Body'
+ recipient=asdf@asdf.com
+ args=
+ for file in '$attachments'
+ file=2013-12-12.pdf
+ touch 2013-12-12.pdf
+ mv 2013-12-12.pdf '/cygdrive/c/Documents and Settings/Eric/My Documents//2013-12-12.pdf'
mv: listing attributes of `2013-12-12.pdf': Invalid argument
+ args=' -a /cygdrive/c/Documents and Settings/Eric/My Documents//2013-12-12.pdf'
+ echo -e Test Body
+ email --from-addr nosender@mydomain.com --from-name 'Automated CSS Downloader' --subject 'Downloaded new file(s) from CSS' -a /cygdrive/c/Documents and Settings/Eric/My Documents//2013-12-12.pdf eric@mydomain.com
email: WARNING: Email address 'and' is invalid. Skipping...
email: FATAL: Could not open attachment: /cygdrive/c/Documents: No such file or directory

ご覧のとおり、パス内のエスケープされたスペースは $args 変数にエクスポートされていません。エラーが「args = ...」の行にあると想定しています。しかし、エスケープされた文字が確実に保持されるように $destinationPath をエスケープする方法がわかりません。

destinationPath で二重引用符 (エスケープスペースなし) を使用しようとしましたが、役に立ちませんでした。$destinationPath を args= 行で二重引用符にしようとすると、余分な引用符がたくさん付いて出力が台無しになります。

どうすればこれを機能させることができますか? 私は $IFS 変数をいじってみましたが、私はそれで何をしているのか本当にわかりません. IFS。

4

2 に答える 2

6

配列なしでこれを行う良い方法はありません。( を使用して行うにはあまり良い方法ではありませんevalが、配列の方が簡単です。)

問題は、各ファイルを最終的に への 1 つの引数にしemailたいが、それらの引数をすべて Bash 変数に蓄積したいことです。それを行う方法はありません。Bash変数を単一の引数として挿入するか("$arg")、または分割された単語の数として挿入することが$argできます( )が、変数が作成されたときにスペースがエスケープされたかどうかに応じて分割されます。これは、Bash は変数に割り当てられた文字列のみを記憶し、エスケープ記号は記憶しないためです。

ただし、すべてのファイル名を正確に 1 つの配列要素にすることができ、Bash に要素ごとに 1 つの引数として配列を挿入させることができるため、配列を使用してそれを行うことができます。

方法は次のとおりです。

# File paths                                                                                                                              
destinationPath="/cygdrive/c/Documents and Settings/Eric/My Documents/"
attachments="\n2013-12-12.pdf"
body="Test Body"
recipient="asdf@asdf.com"


# Prepare attachments                                                                                                             
args=()
for file in $attachments ; do
    file=${file//[ \\n]/}
    touch $file
    mv $file "$destinationPath/$file"
    args+=(-a "$destinationPath/$file")
done

# Send email                                                                                                                      
echo -e $body |
  email --from-addr nosender@mydomain.com \
        --from-name "Automated CSS Downloader" \
        --subject "Downloaded new file(s) from CSS" \
        "${args[@]}" eric@mydomain.com

attachments変数を配列にすることもできます。改行文字が存在することから、実際にはもっと複雑な方法で設定していると思われるので、コードは変更しませんでした。しかし、添付ファイル名にスペースが含まれている場合、現在のコードは機能しません (また、 の値を変更していない限り、forフォームのパラメーター展開によって改行が削除されることは確実です。必要ありません。)$IFSfile=${file//[ \\n]/}

于 2013-06-23T05:04:08.970 に答える
1

文字列で destinationPath を指定する場合は、エスケープされた二重引用符が必要です。

これはうまくいくはずです:

#!/bin/sh                                                                                                                                 

# file paths                                                                                                                              
destinationPath="/cygdrive/c/Documents and Settings/Eric/My Documents/"
attachments="\n2013-12-12.pdf"
body="Test Body"
recipient="asdf@asdf.com"


        # prepare attachments                                                                                                             
        args=""
        for file in $attachments ; do
            file=${file//[ \\n]/}
            touch $file
            mv $file "$destinationPath/$file"
            #HERE YOU NEED ESCAPED DOUBLEQUOTED
            args="$args -a \"$destinationPath/$file\""
        done

        # send email                                                                                                                      
        echo -e $body | email --from-addr nosender@mydomain.com --from-name "Automated CSS Downloader" --subject "Downloaded new file(s) \
from CSS" $args eric@mydomain.com
于 2013-06-23T04:30:43.260 に答える