bashスクリプト関数パラメータの問題

bashスクリプト関数パラメータの問題

なぜエラーが発生するのかわかりません。実際のコードをシミュレートしたテストコードです。ラッパーを作成しfind、すべてのパラメータを受け入れたいので、各パラメータを一重引用符で囲みました。

#!/bin/bash

function find2 {

   ARGS="/usr/bin/find"
   while [[ $# -gt 0 ]]; do
      ARGS="$ARGS '$1'"
      shift
   done
   echo CALLING:  $ARGS
   $ARGS

}

find2 /tmp/test -name "hello.c"    # THIS IS THE DESIRED IMPLEMENTATION (doesn't work)

find '/tmp/test' '-name' 'hello.c'     # THIS IS FOR DEBUGGING (works)

「find2」が動作したいのですが、動作しません。次の結果が表示されます。

CALLING: /usr/bin/find '/tmp/test' '-name' 'hello.c'
/usr/bin/find: `\'/tmp/test\'': No such file or directory
/usr/bin/find: `\'-name\'': No such file or directory
/usr/bin/find: `\'hello.c\'': No such file or directory

ただし、(find2によって生成された)まったく同じコマンドを直接使用すると、うまく機能します。

/tmp/test/hello.c

何が起こったのかわかりません。

ベストアンサー1

(Bashから)値の配列に変更できます。

find2() {

    ARGS="/usr/bin/find"
    ARGS+=( "$@" )
    echo CALLING:  "${ARGS[@]}"
    "${ARGS[@]}"

}

find2 /tmp/test -name "hello.c"

しかし、これはうまくいき、とても簡単です。

find2() {
    ARGS=( "/usr/bin/find" "$@" )
    echo CALLING:  "${ARGS[@]}"
    "${ARGS[@]}"
}

find2 /tmp/test -name "hello.c"

もちろん、直接的な方法も可能です(関数を持つすべてのシェルで):

find2() {    /usr/bin/find "$@";   }

find2 /tmp/test -name "hello.c"

元のコードが失敗するのはなぜですか?

コードが実行するアクションを「確認」するには、set -x 以上を使用できます。次のようにechoをprintfに置き換えます。

find2() {

    ARGS="/usr/bin/find"
    ARGS+=( "$@" )
    printf '<%s> ' CALLING:  "${ARGS[@]}"; echo
    "${ARGS[@]}"

}

find2 /tmp/test -name "hello.c"

実行すると、次のように表示されます。

$ ./script.sh
<CALLING:> </usr/bin/find> </tmp/test> <-name> <hello.c> 

各パラメータは別々の要素です(<>位置に注意してください)。

ただし、ソースコード(printfの追加)では、次のことを行います。

function find2 {

    ARGS="/usr/bin/find"
    while [[ $# -gt 0 ]]; do
        ARGS="$ARGS '$1'"
        shift
    done
    printf '<%s> ' CALLING:  "${ARGS[@]}"; echo
    $ARGS

}   

find2 /tmp/test -name "hello.c"

実行すると、次のようになります。

$ ./script.sh
<CALLING:> </usr/bin/find '/tmp/test' '-name' 'hello.c'>

すべての値は個々のパラメータではなく1つの長いテキスト行です(<>配置に注意してください)。

おすすめ記事