質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
bash

bash(Bourne-again-Shell)は sh(Bourne Shell)のインプリメンテーションに様々な機能が追加されたシェルです。LinuxやMac OS XではBashはデフォルトで導入されています。

シェルスクリプト

シェルスクリプトは、UNIX系のOSもしくはコマンドラインインタプリタ向けに記述されたスクリプト。bash/zshといったシェルによって実行されるため、このように呼ばれています。バッチ処理などに使用されており、テキストファイルに書かれた命令を順に実行します。

Linux

Linuxは、Unixをベースにして開発されたオペレーティングシステムです。日本では「リナックス」と呼ばれています。 主にWebサーバやDNSサーバ、イントラネットなどのサーバ用OSとして利用されています。 上位500のスーパーコンピュータの90%以上はLinuxを使用しています。 携帯端末用のプラットフォームAndroidは、Linuxカーネル上に構築されています。

コマンド

コマンドとは特定のタスクを行う為に、コンピュータープログラムへ提示する指示文です。多くの場合、コマンドはShellやcmdようなコマンドラインインターフェイスに対する指示文を指します。

Q&A

解決済

3回答

4967閲覧

bashのコマンドライン引数のワイルドカード展開

Weapon

総合スコア106

bash

bash(Bourne-again-Shell)は sh(Bourne Shell)のインプリメンテーションに様々な機能が追加されたシェルです。LinuxやMac OS XではBashはデフォルトで導入されています。

シェルスクリプト

シェルスクリプトは、UNIX系のOSもしくはコマンドラインインタプリタ向けに記述されたスクリプト。bash/zshといったシェルによって実行されるため、このように呼ばれています。バッチ処理などに使用されており、テキストファイルに書かれた命令を順に実行します。

Linux

Linuxは、Unixをベースにして開発されたオペレーティングシステムです。日本では「リナックス」と呼ばれています。 主にWebサーバやDNSサーバ、イントラネットなどのサーバ用OSとして利用されています。 上位500のスーパーコンピュータの90%以上はLinuxを使用しています。 携帯端末用のプラットフォームAndroidは、Linuxカーネル上に構築されています。

コマンド

コマンドとは特定のタスクを行う為に、コンピュータープログラムへ提示する指示文です。多くの場合、コマンドはShellやcmdようなコマンドラインインターフェイスに対する指示文を指します。

0グッド

1クリップ

投稿2021/11/01 07:00

前提・実現したいこと

シェルスクリプト(bash)のコマンドラインの引数の値からlsでファイルを取ってこようとしています。
しかしコマンドラインの引数からワイルドカード(*)を使おうとするとその場で展開されてしまうのか上手くいきません。

たとえば

ディレクトリ構造をこのようにした場合
/hoge.txt
/piyo.txt
/script/script.sh

script.shを以下のようにすると

sh

1#!/bin/bash 2IFS=$'\n' 3declare -a command_ls_emb=("$(ls ../* 2>/dev/null)") 4 5for get in ${command_ls_emb[@]} 6do 7 echo "array : $get" 8done

shell

1user:~/test/script$ ./script.sh 2array : ../hoge.txt 3array : ../piyo.txt 4array : ../script: 5array : script.sh 6user:~/test/script$

このlsするための値を引数から得ようとした場合

sh

1#!/bin/bash 2IFS=$'\n' 3declare -a command_ls=("$(ls $1 2>/dev/null)") 4 5for get in ${command_ls[@]} 6do 7 echo "array : $get" 8done

とすると

console

1user:~/test/script$ ./script.sh ../* 2array : ../hoge.txt 3user:~/test/script$

と展開されてしまいます。

考えた対策1

引数で

console

1user:~/test/script$ ./script.sh "../*"

とダブルクオーテーションでくくってやれば大丈夫ですがユーザーに強制するのは優しくありません。

考えた対策2

そこで以下のように記述しても

#!/bin/bash echo $1 echo "double quorts : $1" set -f echo $1 echo "set -f : $1" set +f

それぞれすべて展開されてしまいます。

考えた対策3

取得した引数のディレクトリ判定
ただし
引数で

console

1user:~/test/script$ ./script.sh "../*/x"

とされた場合の抜け道があります。

質問

  1. どのようにすればワイルドカード展開をされずにコマンドライン引数の受け渡しをすればいいのでしょうか

  2. 展開されているのだとは思いますが../*ではなぜ1ファイルしか取得できてないのでしょうか?

  3. 2)と被るかもしれませんが、ワイルドカード展開が回避できないとしてワイルドカード展開された等の判定をすることはできるのですか?

  4. このような状況の回避手段などがあれば教えてください。

よろしくお願いします。

補足情報

Windows10 Pro
WSL Ubuntu 20.04
bash version 5.0.17(1)-release (x86_64-pc-linux-gnu)

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答3

0

ベストアンサー

ワイルドカード展開はスクリプト呼び出し前に行われるので、

sh

1./script.sh ../*

は、

sh

1./script.sh ../hoge.txt ../piyo.txt ../script

と書いたのと同じです。で、$1と第一引数だけ指定したので、../hoge.txtが使われます。
普通に、全引数を"$@"と指定すればいいでしょう。

Bash

1IFS=$'\n' 2declare -a command_ls=($(ls "$@" 2>/dev/null)) 3 4for get in "${command_ls[@]}" 5do 6 echo "array : $get" 7done

あと、("$(ls ~)")"で囲んでしまうと、IFSによる分割は起こらないので囲みません。
下記のようにdeclare -p command_lsで確認してみましょう。

Bash

1IFS=$'\n' 2declare -a command_ls=("$(ls ..* 2>/dev/null)") 3declare -p command_ls 4declare -a command_ls=($(ls ..* 2>/dev/null)) 5declare -p command_ls

投稿2021/11/01 10:46

otn

総合スコア85901

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

ファイル名展開はあくまでも、そのスクリプトを実際に実行するシェルではなく、そのスクリプトを起動する対話シェルの挙動なので、すでに起動されたスクリプトの中では時すでに遅しで、もう何も対処できません。

なので、

  1. どのようにすればワイルドカード展開をされずにコマンドライン引数の受け渡しをすればいいのでしょうか

その対話シェルでファイル名展開が起こらないようにするには、

  • 質問にもあるようにクオートまたはエスケープする
  • set -f する

しかないと思います。

  1. 展開されているのだとは思いますが../*ではなぜ1ファイルしか取得できてないのでしょうか?

../*../hoge.txt ../piyo.txt に展開されて2つの引数として渡されますが、スクリプトでは ls $1 として1つ目の引数しか利用していないですね。

投稿2021/11/01 07:27

編集2021/11/01 07:35
itagagaki

総合スコア8402

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

  1. どのようにすればワイルドカード展開をされずにコマンドライン引数の受け渡しをすればいいのでしょうか

入力するシェルの側が展開してしまうので、渡されるプログラムの方で制御するすべはありません。使うユーザーにエスケープさせるのが正当な手段です。

投稿2021/11/01 07:24

maisumakun

総合スコア146018

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問