バッシュのグロビングと引数の受け渡し


8

次の簡略化されたbashスクリプトがあります

#!/bin/bash

files=("$@")

if [ "X$files" = "X" ]; then
  files=$HOME/print/*.pdf;
fi

for file in "${files[@]}"; do
  ls "$file";
done

引数(ファイル名)をパラメーターとして渡すと、このスクリプトは適切なファイル名を出力します。一方、引数を渡さない場合は、出力されます

/home/user/print/*.pdf: No such file or directory

この場合、ファイル名が展開されないのはなぜですか、どうすれば修正できますか?通常の "files = $ *"よりも優先されることを読んだので、files=("$@")and "${files[@]}"構文を使用していることに注意してください。


どこでfiles=$*、これまで通常の?それは明らかに間違っています。
ステファンChazelas

通常は相対的です。私は配列を使用しない方法を意味しました。それなら何をしますか?
highsciguy 2013年

回答:


10

配列変数ではなくスカラー変数filesとして割り当てています。

 files=$HOME/print/*.pdf

あなたは、いくつかの割り当てている文字列のよう/home/highsciguy/print/*.pdf$files、変数(文字列別名)スカラーを。

使用する:

files=(~/print/*.pdf)

または

files=("$HOME"/print/*.pdf)

代わりに。シェルは、そのグロビングパターンをファイルパスのリストに展開し、それぞれを$files 配列の要素に割り当てます。

グロブの展開は割り当て時に行われます。

非標準のsh機能を使用する必要はありません。次のように記述することshで、システムの代わりに使用できますbash

#!/bin/sh -

[ "$#" -gt 0 ] || set -- ~/print/*.pdf

for file do
  ls -d -- "$file"
done

set"$@"位置パラメータの配列を割り当てることです。

別のアプローチは、スカラー変数にグロビングパターンを格納することでした。

files=$HOME/print/*.pdf

$files 変数が展開されたときにシェルにグロブを展開させます。

IFS= # disable word splitting
for file in $files; do ...

ここでは、$filesは引用されていないため(通常は行うべきではありません)、その展開は単語分割(ここでは無効にしました)およびグロビング/ファイル名の生成の影響を受けます。

したがって、*.pdf 一致するファイルのリストに展開されます。ただし、$HOMEワイルドカード文字が含まれている場合は拡張することもできるため、配列変数を使用することをお勧めします。


4

配列のない古いシェルfiles=$*などfiles=~/print/*.pdfで見たことがありますls $files

二重引用符で囲まれていない変数置換は、変数の値を、一致するファイル名がある場合にそれに一致するシェルワイルドカードパターンの空白で区切られたリストとして解釈します。例えば、後にfiles=~/print/*.pdfls $files同じようなものに展開ls引数と/home/highsciguy/print/bar.pdf/home/highsciguy/print/foo.pdf場合などfiles=$*、この割り当ては、間にスペースをスクリプトに渡される引数、および連結ls $filesそれらをバックアウト分割を。

空白文字やグロビング文字を含むファイル名があると、これらすべてが機能しなくなります。そのため、この方法で処理を行うべきではありません。代わりに配列を使用してください。

files=("$@")
if ((${#files[@]} == 0)); then
  files=("$HOME"/print/*.pdf)
fi

ご了承ください

  • すべての配列割り当てでは、配列値を括弧で囲む必要があります:var=(…)
  • 配列が空かどうかをテストするには、その長さを確認します。"$files"ときに空であるfiles、その要素インデックス0の未設定または空の文字列である配列です。また[ "X$foo" = "X" ]$fooが空であるかどうかをテストするための古い方法[ -n "$foo" ]です。すべての最新のシェルは正しく実装されています。bashでは、を使用できます[[ -n $foo ]]

配列をサポートしないシェルでは、実際には配列が1つあります。それは、シェルまたは現在の関数に対する位置パラメーターです。ここでは、files配列は実際には必要ありません。実際には、位置パラメーターを使用する方が簡単です。

#!/bin/sh
if [ "$#" -eq 0 ]; then
  set -- ~/print/*.pdf
fi
for file do 
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.