私のbashスクリプトでは、findを使用して、ワイルドカードでフォルダー名を取得します。
for i in $(find ${directory} -mindepth 1 -type d -name ${wildcard});
do
stuff=doStuff ${i}
done
doStuff() {
echo ${1}
return ${1}'/hello';
}
問題は、これを実行すると次のエラーが発生することです($ {i}が 'home/me/my_directory'に対応しているとしましょう)。
line 111: '/home/me/my_directory': is a directory.
(111行目は「doStuff」のある行です)
私はこれをやってみましたが、役に立ちません:
for i in $(find ${directory} -mindepth 1 -type d -name ${wildcard});
do
stuff=doStuff "${i}"
done
どうやら、それはプログラムがディレクトリを実行しようとしているためですが、操作できる文字列としてそれを必要としています。
ここでは、引用とコマンド置換が問題になります。
実行している特定の問題は、シェルが環境変数_/home/me/my_directory
_を使用して_stuff=doStuff
_というコマンドを実行しようとしているためです。
あなたが本当に望んでいること(私が正しく解釈している場合)は、_$i
_の値を引数としてdoStuff
を実行し、変数stuff
に出力を割り当てます。これを行う方法は、コマンドを$()
でラップすることです。例えば:
_stuff="$(doStuff "$i")"
_
すべてを引用符で囲む方法にも注意してください。これは、シェルが不要なものをWordに分割しないようにするためです(_/foo/bar baz
_の単一の引数を_/foo/bar
_とbaz
に変換します)。
また、関数の出力は、return
ではなく、戻り値として使用されるものです。
より多くの引用符を使用する必要があるため、他のすべてに引用符を追加する必要もあります。ここにあなたのスクリプトの完全なバージョンがあります:
_doStuff() {
echo "${1}" >&2
printf '%s/hello' "$1";
}
IFS=$'\n'
for i in $(find "${directory}" -mindepth 1 -type d -name "${wildcard}");
do
stuff="$(doStuff "${i}")"
done
_
使用してみる前に、関数定義を配置する必要があります。シェルは、コンパイルされたプログラムのように解析されず、ファイルを何度も通過します。それはトップダウンです。
また、doStuff
を変更して、echo
を端末に表示するSTDERRに送信し、printf
をSTDOUTに送信して、変数stuff
にキャプチャします。
ディレクトリのいずれかに改行が含まれている場合でも、問題が発生することに注意してください。ただし、これはシェルの制限です。ファイルパスに含めることができない唯一の文字はNULL文字(_\0
_)です。ただし、bashやその他のシェルでは文字列にNULL文字を格納できないため(すべてではないが、多くの場合zshは可能です)、区切り文字として使用することはできません。
これはかなりの努力ですが、実際には単純なスクリプト言語であるにもかかわらず、bash
をプログラミング言語のように書こうとしていることを示しています。あなたのstuff=doStuff arg
構造の問題は、bash
にとってそれがあなたがそれが何を意味するかを意味しないということです。 bash
に対して、stuff=doStuff
は変数の割り当て、arg
はコマンドです。次の2つのリンクを読むことをお勧めします。
あなたが持っているものに似たものの作業バージョン
doStuff () {
echo "$1/hello"
}
stuff=$(doStuff "$i")
エラーを示す行は、あなたが思っていることをしていません:
最初に環境変数を文字列 "doStuff"に設定し、次に$ {i}をコマンドとして実行しようとします。また、$ {i}はディレクトリであるため、指定されたエラーメッセージで失敗します。