したがって、 bash
でこのようなことを行う 他のほとんどのシェルは、複数のサブディレクトリまたはサブディレクトリ内のファイルを作成するために機能しません…
mkdir */test
touch */hello.txt
もちろん、これを実際に行う方法はたくさんあります。私の好みの方法は、 find
を使用することです。 可能な場合は、 for
を使用するのではなく ループ、主に読みやすさのため。
しかし、私の質問は、なぜ上記が機能しないのかということです。
私が理解していることから、完全な宛先ファイル/パスが存在しないためですが、 mkdir
> またはtouch
。私はいつも先に進んでいて、実際に質問したことはありません。
しかし、これについて、私が完全に理解するのに役立つ適切な説明がある人はいますか?
承認された回答:
あなたが見逃しているかもしれない点-多くの人が問題を抱えていること-特に*nixに来る前に他のオペレーティングシステムの経験がある場合
-他の多くのOSでは、コマンドラインは通常、コマンドに渡されます 適切と思われる処理を行います。たとえば、Windowsコマンドプロンプトでは、
rename *.jpeg *.jpg
一方、* nixでは、個々のコマンド( mv
など)のプログラマーの仕事を簡素化するために
)、ワイルドカード
(引用符で囲まれていないかエスケープされていない場合)はシェルによって処理されます。
ワイルドカードが引数となるコマンドのインターフェースと機能に依存しない方法で
。
コマンドライン引数としてファイル名を使用するほとんどのプログラムは、それらのファイルが存在することを期待しています
(はい、 mkdir
およびtouch
その規則の例外です。mkfifo
も同様です。 、 mknod
、および、部分的には cp
、 ln
、 mv
、および名前の変更
;
そしておそらく他にもあります)、
したがって、シェルがワイルドカードを
存在しないファイルの名前に展開することは実際には意味がありません。
そしてシェルの場合(そして、それによって、私はすべてを意味します shell –
Bourne、bash、csh、fish、ksh、zshなど)例外を別の方法で処理するには
おそらく面倒です。
そうは言っても、あなたが望むような結果を得るにはいくつかの方法があります。
ワイルドカードが何に拡張されるかがわかっていて、
長くない場合は、ブレース拡張を使用して生成できます:
touch {red,orange,yellow,green,blue,indigo,violet}/rgb.txt
より一般的な解決策:
sh -c 'for arg do mkdir -- "$arg"/test; done' -- *
Gillesは、
bashでそれを行う別の方法を見つけるのを手伝ってくれました。
benbradley=(*)
mkdir "${benbradley[@]/%//test}"
明らかにbenbradley
ここでは単なる識別子です。任意の名前を使用できます
(例:任意の1文字)。
これを正しく行うには数回の試行が必要だったので、分解させてください:
識別子 =値
識別子という名前の(スカラー)変数を作成します
(まだ存在しない場合)そして値valueを割り当てます
それに。
たとえば、G =Man
。
$識別子を使用してスカラー変数を参照できます
;
たとえば、$ G
、または、より安全に、${識別子として }
。
たとえば、$ Gage
および$Gilla
未定義の可能性がありますが、
ただし$ {G} age
管理
です および${G} illa
Manilla
です 。識別子 =( 値1 値2 …)
identifierという名前の配列変数を作成します
(まだ存在しない場合)そしてリストされた値をそれに割り当てます。
たとえば、
spectrum=(red orange yellow green blue indigo violet)
または
all_text_files=(*.txt)
$名前
最初の要素を参照します(したがって、かなり役に立ちません)。
任意の要素を${ nameとして参照できます [添え字 ]}
;
たとえば、 $ {spectrum [0]}
red
および${spectrum [4]}
blue
です 。
そして、 $ { nameを使用できます [@]}
および${ name [*]}
配列全体を参照します。
それで、ここにそれはバラバラになっています:
" ${ benbradley[@] / % / /test } "
${パラメータ /パターン /文字列 }
${パラメータを展開します }
patternの最長一致
を置き換えます文字列
。-
patternの場合
#
で始まります 、
parameterの展開された値の先頭で一致する必要があります
。
patternの場合
%
で始まります 、
parameterの展開された値の最後で一致する必要があります
。
つまり、
%(the-rest_of_the_pattern)
のように動作します
(the-rest_of_the_regex)$
(はい、それは少し後ろ向きに見えます)。
つまりパターン
それは単なる%
単なる$
である正規表現のようなものです –
入力文字列(検索スペース)の末尾と一致します。
- そして私は
stringを使用しています
/ test
の 。
したがって、これにより、パラメーターの末尾が/ test
に置き換えられます。 (つまり、/ test
を追加します パラメータに)。 -
${パラメータに関するもう1つのこと /パターン /文字列 }
直感的ではないのは、常に}
で終わります 。
必要はなく、できません 、3番目の/
で終了します 。
したがって、/
文字列
区切り文字として解釈することはできません。
したがって、文字列
を使用できます。/ test
の/
をエスケープする必要はありません 。 パラメータの場合
は配列変数です@
で添え字が付けられています または*
、
置換操作は、配列の各メンバーに順番に適用されます。- 配列を
${ nameとして参照する場合 [@]}
($ { nameではなく [*]}
)結果を二重引用符で囲みます。
配列の要素の整合性を維持します
(つまり、スペースやその他の特殊文字を保持します)
個別の要素を結合せずに、 1つの長い単語。