
「4800483343」はディレクトリで、「file1」と「file2」はその中にある2つのファイルです。
なぜ次のような状況が発生しますか?
$ ls 4800483343
file1 file2
$ md5sum 4800483343/*
36468e77d55ee160477dc9772a99be4b 4800483343/file1
29b098f7d374d080eb006140fb01bbfe 4800483343/file2
$ mv 4800483343 4800[48]3343
$ md5sum 4800[48]3343/*
md5sum: 4800[48]3343/*: No such file or directory
$ md5sum '4800[48]3343'/*
36468e77d55ee160477dc9772a99be4b 4800[48]3343/file1
29b098f7d374d080eb006140fb01bbfe 4800[48]3343/file2
この問題を引き起こす可能性がある他の文字は何ですか?
答え1
元の質問に答える
角かっこがシェル拡張を防止する理由
角かっこはシェルの拡張を防ぎませんが、引用符は避けます。
実際に実行したコマンドは次のようになりました。
これにより、次のファイルでmd5sumが実行されますdir/
。
$ md5sum d[i]r/*
02fdd7309cef4d392383569bffabf24c dir/file1
db69ce7c59b11f752c33d70813ab5df6 dir/file2
これにより、角かっこが拡張されないように引用符がdir
移動されます。d[i]r
$ mv dir 'd[i]r'
dir
もう存在しないディレクトリを探します。
$ md5sum d[i]r/*
d[i]r/*: No such file or directory
引用符のため、次のエントリは次の名前の新しいディレクトリにありますd[i]r
。
$ md5sum 'd[i]r'/*
02fdd7309cef4d392383569bffabf24c d[i]r/file1
db69ce7c59b11f752c33d70813ab5df6 d[i]r/file2
修正された質問に答えてください
修正された質問にはディレクトリ4800483343があり、次のコマンドが実行されます。
mv 4800483343 4800[48]3343
このコマンドを実行したときに発生することは、globが4800[48]3343
既存のディレクトリと一致するかどうかによって異なります。一致するディレクトリがない場合は、それ自体が4800[48]3343
展開され、4800[48]3343
ディレクトリ4800483343
がディレクトリに移動します4800[48]3343
。
ついに:
このコマンドは、
md5sum 4800[48]3343/*
globと一致するディレクトリがないため、「該当するファイルまたはディレクトリがありません」というエラーを返します4800[48]3343
。引用符はグローバル拡張を防ぐため、このコマンドは
md5sum '4800[48]3343'/*
ファイルを正しく検索します。
グローバル例
2つのファイルを作成しましょう。
$ touch a1b a2b
次の球を見てみましょう。
$ echo a[123]b
a1b a2b
$ echo a?b
a1b a2b
$ echo *b
a1b a2b
答え2
角かっこ式は任意の数を表します。一つ可能な一致文字一つキャラクターの位置。この単純な経験則は、マルチバイト文字と[[.
組み合わせ要素.]]
および/または同等クラスの処理を開始するとぼやけてしまう傾向がありますが、それでもなお、これらの文字に対する複数文字の一致を完全にサポートしていないプログラムがたくさんあります。すべてのロケールに対して、ASCII 数値 0-9 は常に一致し、角括弧式内で順番にソートされます。 POSIXでは、少なくとも最後の数字は真でなければなりません。[[=
=]]
たとえば、
cd /tmp
for d in 0 1 2 3 4 5 6 7 8 9; do mkdir "$d"; done
ls [0123]
0:
1:
2:
3:
デフォルトでは、単一の[
角かっこ式]
シェルglobはより具体的な?
char globです。
echo ?/; echo [2468]/
0/ 1/ 2/ 3/ 4/ 5/ 6/ 7/ 8/ 9/
2/ 4/ 6/ 8/
したがって、シェル glob は、次の4800[48]3343
2 つの現在のディレクトリファイル名のいずれかと一致します。
480043343
480083343
...しかし、そうではありません...
4800483343
4800843343
4800[48]3343
ファイル名にリテラル角かっこを使用するには、角かっこ式で角かっこを一致させることができます。
touch 4800\[48]3343
echo 4800[[]48[]]3343
4800[48]3343
シェルの角かっこワイルドカードにも引用符があまり必要ありません。シェルは、リストのコンテキストで glob 式の始まりとして 3 文字を認識します。
* ? [
左角かっこがない右角括弧は別の文字にすぎず、引用する必要はありません。
echo ]
]
したがって、ペアの開かれた括弧だけを引用すると、常に文字通り解釈されます。それ以外の場合は、いつでもワイルドカードを完全に無効にできます。
set -f
余暇に戻ってください。
set +f
答え3
4800483343
ディレクトリ名をに変更すると、メタ文字をエスケープするために引用形式を使用する4800[48]3343
必要があります。[ ]
これはすべて機能します:
$ ls 4800\[48\]3343/*
$ ls "4800[48]3343"/*
$ ls '4800[48]3343'/*
すべて正しく印刷されます。
4800[48]3343/file1 4800[48]3343/file2
ただし、メタ文字を保持し[
て]
引用符なしでそのままにしておくと、「パス名の拡張」の角括弧の説明として解釈されます。 bashのマニュアルで「パス名拡張」を検索すると、次のようになります。
[...]は含まれている文字の1つと一致します。
これがどのように機能するかを説明するテキストがあります。簡単に言うと:
A [abc] will match ONE character, either an `a`, an `b` or an `c`.
したがって、引用符がない場合またはに4800[48]3343
一致します。どちらもディレクトリではなく、ディレクトリがないため拡張されません。より複雑な拡張はディレクトリと一致し、拡張が機能します。480043343
480083343
4800[48]3343
ls 4800[48]3343/*
$ ls 4800$'\133'[48][48]$'\135'3343/*
しかし、たぶん私はここで話題に深く入っているかもしれません。 :-)