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

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

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

SSH(Secure Shell)は、セキュアチャネルを通してデータを交換するためのネットワークプロトコルです。リモートサーバーへのコマンド実行やファイル転送を行う時に一般的に使用されます。

Linux

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

Q&A

解決済

4回答

3733閲覧

ls *(アスタリスク)のコマンド展開が実行される条件

toroleaman

総合スコア95

SSH

SSH(Secure Shell)は、セキュアチャネルを通してデータを交換するためのネットワークプロトコルです。リモートサーバーへのコマンド実行やファイル転送を行う時に一般的に使用されます。

Linux

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

0グッド

0クリップ

投稿2020/09/23 11:22

あるサーバ(YYY.YYY.YYY.YY)で

ssh testusert@XXX.XXX.XXX.XXX ls /tmp/test*.data

と実施するとXXX.XXX.XXX.XXX というサーバには、/tmp/test20200923.dataというファイルが存在するので、
test20200923.data
というデータが取れます。

次に
YYY.YYY.YYY.YYサーバ上に
/tmp/test123.data
というファイルを作成すると、

ssh testusert@XXX.XXX.XXX.XXX ls /tmp/test*.data
を実施すると、
ls: /tmp/test123.data にアクセスできません: そのようなファイルやディレクトリはありません。

というエラーが発生します。

*が、展開されて、
ssh testusert@XXX.XXX.XXX.XXX ls /tmp/test123.data
が実行されるため、上記のエラーが発生していると考えていますが、
ローカルに一致するファイル名が存在する場合と存在しない場合で、
*が展開される、されないが変わることに違和感を感じています。

ssh testusert@XXX.XXX.XXX.XXX 'ls /tmp/test*.data'
とすることで、問題は回避できるのですが、
*の展開がローカルにファイルがある場合とない場合で挙動が異なる理由について、
ご存知でしたら教えてほしいです。

参考情報
https://qiita.com/emasaka/items/a59335c74220b3641639

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

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

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

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

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

guest

回答4

0

ローカルに一致するファイル名が存在する場合と存在しない場合で、
*が展開される、されないが変わることに違和感を感じています。

*の展開がローカルにファイルがある場合とない場合で挙動が異なる理由について、
ご存知でしたら教えてほしいです。

質問文を見る限り挙動は理解されているようで、疑問点について説明出来ているのかどうかわからないのですが…、

」の展開はローカルのシェルがまず行っており、その際、ローカルに「」で展開出来るファイルがあれば展開された状態の文字列でsshコマンドでリモートに渡され、ローカルで「」で展開できなければ「」のままsshでリモート先に渡されリモート先のシェルでその「*」が展開されるということだと思います。

ssh testusert@XXX.XXX.XXX.XXX 'ls /tmp/test*.data'
とすることで、問題は回避できるのですが、

こちらの場合は、ローカルのシェルの「」展開が行われずに「」がそのままsshへ渡るので、ローカル側のファイルの存在の影響を受けません。

今の質問文からはそれ以上の説明は自分には出来ませんが、何が知りたいかさらに掘り下げて補足してもらえば説明出来るかもしれません。

投稿2020/09/23 11:49

編集2020/09/23 12:04
hidezzz

総合スコア1248

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

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

toroleaman

2020/09/23 15:35

>「*」の展開はローカルのシェルがまず行っており、その際、ローカルに「*」で展開出来るファイルがあれば展開された状態の文字列でsshコマンドでリモートに渡され、ローカルで「*」で展開できなければ「*」のままsshでリモート先に渡されリモート先のシェルでその「*」が展開されるということだと思います。 これが仕様であるというのが、なぜなのか? *をリモートで展開しないのは、なぜなのか? というのが、最初の疑問でした。bashを作った人がそのように決めたということであれば、 納得せざるを得ないのですが。。 回答ありがとうございました。
hidezzz

2020/09/23 16:46 編集

> これが仕様であるというのが、なぜなのか? bashがユーザからコマンドラインで指定されたコマンドを実行するに先立って「*」展開するという単純なルールに従っているだけです。後述しますがそうでないとbashに仕様追加が必要になってしまうからです。 > *をリモートで展開しないのは、なぜなのか? すべてローカルのファイルシステム上で完結するコマンドについては、bashがローカルファイルシステム上のファイルに基づいて「*」展開するという仕様は合理的なものであると思います。 質問の例ではssh(によるリモートでのコマンド)の実行をしているわけですが、bashは与えられたコマンドがリモートで実行されるかどうかを区別しません。というかbashにとってはsshというコマンドをユーザーの指示されるままに実行しているだけです。 仮に「*」がリモートで展開される場合があるという仕様を実現するためにはbashが実行されるコマンドの性質によって「*」展開すべきかどうかを判断する必要が出てきますが、それは不可能では無いかもしれませんがそこまでやる必要性を感じません。(リモートでの「*」展開が必要なコマンドに対しては「このコマンドはリモートで実行される」属性フラグを付けるとか、bashにリモートで実行されるコマンドのリストを何らかの方法で覚えさせておくとか、になるでしょうか…) それよりは「*」展開はシェルが行うようにして、そうしてほしくない場合はユーザーが明示的に指定するのが良いやり方だと感じます。(今ある仕様に毒されているだけと言われるかもしれませんが…。) 自分の場合は、 ssh testusert@XXX.XXX.XXX.XXX 'ls /tmp/test*.data sshによるリモート実行する際に自然と上記のような書き方をするようになっています。
guest

0

ベストアンサー

理由というか、shやbashの場合、*?等は、そのディレクトリにマッチするファイルがあれば展開されて、マッチしなければそのまま*?残されます。

tcshやzshだと、マッチするファイルが無いとエラーになります。
(bashだとオプション設定でエラーになるように変更できます。zshででエラーにしない設定があるかも知れません)

というふうに、シェル開発者の間でも、マッチしないワイルドカードをどうすべきかについては意見が分かれていますね。

shがマッチしない場合にそのまま残す理由については、shの機能が拡充していく際に過去との互換性を保つためだったんだと思います。

投稿2020/09/23 11:46

otn

総合スコア85901

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

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

toroleaman

2020/09/23 15:38

なるほどです。tcshやzshで挙動が異なるあたり、 開発者でも悩んで決まった仕様なのだと想像できます。 回答ありがとうございました。
guest

0

*の展開がローカルにファイルがある場合とない場合で挙動が異なる理由について、...

マッチするファイル名が見つかるかどうか、ですね。

man bash

パス名展開
-f オプションが指定されていなければ、単語分割を行った後に bash はそれぞれの単語が *, ?, [ を含んでいるかどうか調べます。 これらの文字のいずれかが見つかると、その単語は パターン とみなされ、 パターンにマッチするファイル名を アルファベット順にソートしたリストに置換されます。 マッチするファイル名が見つからず、かつシェルのオプション nullglob が無効ならば、その単語は変更されずにそのまま残ります。

投稿2020/09/23 11:44

shiketa

総合スコア4061

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

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

toroleaman

2020/09/23 15:50

回答ありがとうございます。nullglobで、パス名展開に失敗した場合の挙動を変更できるのですね。
guest

0

なんか勘違いしていませんか。

ssh testusert@XXX.XXX.XXX.XXX ls /tmp/test*.data
「/tmp/test20200923.data」というファイルが存在する場合

も、二回目の
ssh testusert@XXX.XXX.XXX.XXX ls /tmp/test*.data
「/tmp/test123.data」と言うファイルが存在しない(ローカルにしかない)

も、同じようにリモートサーバの/tmpの情報を取得しています。

ローカルにいくらファイルを作成しても、
リモートの状態は変わりませんよ。

>>ローカルに一致するファイル名が存在する場合と存在しない場合で、
>>*が展開される、されない

は変わりません。単にリモートにそれに該当する
ファイルが有るか無いかだけです。

投稿2020/09/23 11:50

hana_yama_san

総合スコア923

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

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

toroleaman

2020/09/23 15:30

これが違うですよ。。。 *が展開されてしまうんです。
hana_yama_san

2020/09/24 10:27

失礼しました。 質問文をよく読んでいなかったですね。 sshのコマンド実行はクオートするものと決め付けて 生活していたもので・・・
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問