たとえば、名前が 1 つまたは複数のマイナス記号で始まるファイルがある場合、多くの--1
コマンドの引数としては使用できません。走っても
cat --1
ファイルの内容の代わりに認識できないオプションのエラーメッセージが表示されます。
cat: unrecognized option '--1'
入力しても同じ効果が出ます。
cat "--1"
cat '--1'
cat \-\-1
何も動作しません。 「-」で始まるファイルはファイルシステムでは違法ではありませんが、cliやスクリプトでは使用するのがかなり難しいです。わかりましcat
たgrep
。
cat <--1
これはうまくいきますが、
rm --1
どちらも機能しないため、コマンドを別のコマンドに置き換えることも困難です。結局、とても不便です。そのようなファイル名を使用しない以外の一般的な回避策はありますか?
しかし、名前ファイルが単一-
で、ほとんどのコマンドがそれを理解できる場合はstdin
そうではありませんか?
mv
また、コマンドを使用してスクリプト内のファイル名を変更できないため、このようなファイル名を使用しないことは困難です。
答え1
慣例は、aで始まるのはすべて-
オプションです。 。で始まるファイル名と競合します-
。この問題を解決するために、ほとんどのコマンドはそれを--
オプションの終了タグとして認識します。次の内容は--
オプションとして認識されず、文字通りファイル名と見なされます。
例えば
cat -- --1
または
rm -rf -- --1
別の方法は、パスにファイル名を修飾することです。
例えば
cat ./--1
でも
cat /home/username/foo/--1
改行を含むさまざまな文字を含めることができます-
。
質問に答えるには:catやgrepなどのコマンドがマイナス記号で始まるファイルを認識できないのはなぜですか?コマンドラインは単なる文字列だからです。シェルはいくつかのファイル名拡張、いくつかのトークン化、いくつかの変数置換を実行しますが、最終的にプログラムは文字列配列を受け取ります。
オプションを表す文字列とファイル名を表す文字列をどのように分離できますか?一部のウォッチャーキャラクターによって。 Unix / Linuxの世界の習慣は-
Centinel文字を使用することです。 a で始まるすべては-
オプションです。まあ、ほとんどすべて。オプションの引数はで始まるかもしれませんが、-
これは個々のプログラムの詳細です。
すべてのプログラムがこの規則に従うわけではありません。確かに最も人気のある例は次のとおりですdd
。
dd if=/dev/random of=whatfreespace
dd
=
ファイル名は記号の後に表示されるように認識されます。
すべてではありませんが、ほとんどのGNUプログラムはGNU getoptの規則に従います。短いオプションは、およびで始まり、-
長さは単一文字で、長いオプションはおよびで始まり、長さは少なくとも--
2文字です。--
これはそれ自体オプションの終わりを示し、そのマークの後の文字列はオプションとして認識されません。詳しくはお読みください。プログラムパラメータの構文規則GNU libcのマニュアルにあります。
GNUルールに部分的に従うプログラムの例は次のとおりですfind
。
find -not -name porn -delete
オプションとオプションではないオプションを区別するためにfind
使用されます-
が、長いオプションと短いオプションを区別するわけではありません。--
オプションの終わりとして識別されます。各プログラムは、オプション、ファイル名、その他を識別する一意の方法を定義できます。
単一文字をstdinとして解釈する規則は、文字列配列内で-
単一文字を見つけるときにそれらを解釈する方法の規則でもあります。-
答え2
ダッシュで始まるすべての項目はオプションと見なされます。オプションのように見えないように、ファイル名の前にパスを追加できます。
cat ./--filename
答え3
cat -- --filename
オプションの検索を中止するには、指示に従います。第三者アプリケーションがダッシュファイル名を処理する方法がわからないため、このアプローチには潜在的な問題があります。ただし、POSIXバイナリなどはcp, rm, cat
これらのダッシュを処理する方法を知っています。
答え4
より一般的には次のようになります。
cat $options_and_or_file_patterns_or_stdin_if_dash
cat "$option_or_file_or_stdin_if_dash"
cat -- "$file_or_stdin_if_dash"
cat < "$file"
cat - < "$file" # same as above