ファイル名のシェル展開(A | B)?


9

orたとえば、ファイルを読み取るときにシェルの選択肢を拡張することは可能ですか?

つまり、たとえば、ファイル内のAまたはBに一致するgrepような構文をサポート(A|B)します。

同様に、これらのファイルがある場合:

file1.txt
file2.txt
file3.txt
file4.txt
file5.txt

私は何ができるcat file{1..5}.txtbash、それは範囲を拡大するよう、。いくつかのファイルに対してこれを行う同等の方法はありますか?

たとえばcat file(1|5).txt、これら2つだけを印刷しますか?

回答:


16

数字に一致する標準のファイル名グロビングパターンは[0-9]です。これは1桁に一致します。

cat file[0-9].txt

これらのうち2つだけを選択するには:

cat file[25].txt

9より大きい数値の場合、ブレース展開が役立ちます(ただし、グロビングパターンとブレース展開の違いについては、下記の注を参照してください)。

cat file{25..60}.txt

繰り返しますが、ブレースの展開では、個々の数値も使用できます。

cat file{12,45,900,xyz}.txt

(上記の例では、ブレース展開は算術ループを含まず、指定された文字列に基づいて名前を生成するだけであることに注意してください)。

ではbashextglobシェルオプションを有効(shopt -s extglob)にすると、次も機能します。

cat file@(12|45|490|foo).txt

@(...)パターンが含まれてのいずれか一致する|-delimitedパターン。


展開パターンとしての[...]and @(...)と中括弧の展開の違いは、中括弧の展開がコマンドラインで生成され、現在のディレクトリ内の既存の名前と実際には一致しない可能性があることです。ファイル名のグロビングパターンは名前に一致しますが、可能な名前がすべて存在しない場合でも、シェルは文句を言いません。場合全く一致する名前が存在しない場合を除き、また、パターンは、膨張していないこと残るnullglobシェルオプションが設定されている場合にパターンを除去し、。

例:

touch file1

ls file[0-9]

ここでは、のファイルリストのみfile1が表示されます。

見つからない文句を言うだろう、などls file{0..9}lsfile0file2

次の例では、最初のコマンドは指定されたパターンに一致する既存の名前のみを操作し、2行目はまだ存在しないファイルを作成します。

touch file[0-9]

touch file{0..9}

@thecarpy申し訳ありませんが、これはたとえばと一致するパターンではありませんfile45.txt。ブラケット表現[...]は正規表現と同じように機能しますが、「ない」と言う!代わりに使用し^ます。[...]パターンは常に単一の文字にマッチします。
クサラナンダ

あなたが正しいです!ところで、私{1,2}もPOSIXに準拠していません...今日、いくつかの新しいことを学びました!
thecarpy

2
中括弧の展開が実際のファイルと一致する必要がないという事実は、それを使用して(例えば)渡すパターンを生成したりgrep、に渡すURLを生成したりする場合などに非常に役立ちますが、curl混乱を招く可能性もあります。グロブの操作に慣れている人に。
ケビン

@ケビン正しい。ブレース展開は、ファイル名に関するものである必要はありません。
クサラナンダ

7

使用する構文はfile{1,2}file1およびに評価される構文file2です。

$ ls
$ touch file{1,2,3,4,5,6,7,8,9}
$ ls
file1  file2  file3  file4  file5  file6  file7  file8  file9

Inianが以下でも指摘しているようにtouch file{1..9}、この例の場合は簡単に実行できます...

$ ls
$ touch file{1..9}
$ ls
file1  file2  file3  file4  file5  file6  file7  file8  file9

次のような複数の式を使用することもできます。

$ ls
$ touch file{1..9}{a..z}
$ ls
file1a file1b file1c
[...]
file9x file9y file9z

はい、上記は234(926)のファイルを作成します。


1
このfile{1,2} 構文はまた、ファイル名を変更すると便利です:mv some_very_long_filename.txt{,.bak}
エリックDuminil

6

はい、bashシェルでブレース展開を使用できます。いくつかのファイルについてはfile{1..2}、ちょうどまたは同じようにfile{1,2}

または、場合によってはファイルが存在しないことが心配な場合は、単純なループを実行します。

for file in file{1..4}.txt; do
    [ -f "$file" ] || continue
    echo "$file" # Do other actions on file here
done

または、単に連結することがファイルに対する唯一の操作であり、どの時点でも存在しなかった可能性があるファイルがわからない場合は、catそれらだけを使用してエラーを抑制します。標準エラーを/dev/nullにリダイレクトすると、ファイルが利用できない場合にエラーが抑制されます。

cat file{1,5}.txt 2>/dev/null

またはfile[15]、ファイルが見つからなかった場合にエラーについて文句を言わないglob式を使用します。

cat file[15].txt

2
いいえ、ファイルが存在しないという心配はありません。2つのファイルの内容に番号を付けて表示したかっただけですが、連続していないため、file{1,5}カンマ構文だけで欠けていました。
ジョーヒーリー
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.