一度に複数のサブディレクトリを作成する

一度に複数のサブディレクトリを作成する

/多くのディレクトリを含むディレクトリがあり、/mydir各ディレクトリは同様の構造を持つ必要があるとします。/hisdir/herdir

各ディレクトリにはディレクトリとその中にファイルが/含まれている必要があります。docdoc1.txt

人々は素朴に自分ができると思うかもしれません。

mkdir */doc
touch */doc/doc1.txt

しかし、それは間違っています。なぜなら、それはワイルドカードが機能する方法ではないからです。

cpある例では、構造体を一度だけ作成し、別の例に渡すことなくこれを行う方法はありますか?

それ以外の場合、既存のファイルを上書きせずに上記の回避策を実行する方法はありますか(mydir保存するデータの一部がある構造がすでに含まれていると仮定します)。

編集:可能であればスクリプトの使用を避けたいです。

答え1

Bashでは、次の行のようなものを使用してください。

mkdir -p {mydir,hisdir,herdir}/doc
touch {mydir,hisdir,herdir}/doc/doc1.txt

この{...}構文は「括弧拡張」と呼ばれ、次のようになります。パス名拡張ここで、ファイル名は必ず存在しなければならず、生成された結果はすでに存在するものと一致する必要はありません。これらの-p方法は、必要に応じてパスのすべてのネストされたコンポーネントを生成します。それ以外の場合、mkdirが親ディレクトリの前に最終的な「doc」ディレクトリを作成しようとするとエラーが発生します。

(例については、bashのマニュアルページを確認してください。このようなサブディレクトリを作成するのが一般的なユースケースです。)

mydir、hisdor、herdirがすでに存在していて、それを再入力したくない場合は、Stéphane Chazelasのソリューションがおそらく最も賢いでしょう。しかし、常にそうしない限り、スマートは常に最善ではありません。 bash配列拡張がオフになっていることを覚えていません。カフと私は多くの下級システム管理者がそれを認識しないと確信しています。この場合は、find次のようにループまたはを使用することをお勧めします。

find . -maxdepth 1 -mindepth 1 -type d \
   -execdir mkdir {}/doc \; -execdir touch {}/doc/doc1.txt \;

しかし、実際に単純なループの利点は、単純で、もはや入力を必要としないということです!

答え2

そしてzsh

dirs=(*(/))
mkdir -- $^dirs/doc
touch -- $^dirs/doc/doc1.txt

(/)ワイルドカード修飾子/選択ディレクトリのみを意味します。

$^array(演算子を連想させるrc^は、配列で括弧を開く型の拡張なので$^array/doc{elt1,elt2,elt3}/docここでelt1elt2elt3配列の要素です)。

次のようにすることもできます。

mkdir -- *(/e:REPLY+=/doc:)
touch -- */doc(/e:REPLY+=/doc1.txt:)

e選択したファイルに対して特定のコードを実行する別のグローバル修飾子はどこにありますか?

そしてrc/ es/ akanga

dirs = */
mkdir -- $dirs^doc
touch -- $dirs^doc/doc1.txt

^これは、拡張接続演算子に似た演算子を使用します。

rcサポートしていないワイルドカード修飾子(これはzsh専用の機能です)。*/すべてのディレクトリに展開とディレクトリシンボリックリンク、そして/添付されました。

そしてtcsh

set dirs = */
mkdir -- $dirs:gs:/:/doc::q
touch -- $dirs:gs:/:/doc/doc1.txt::q

これは:x変数拡張にも適用できる履歴修飾子です。:gsグローバルな選択肢です。:q 引用符特定の文字の問題を防ぐ単語です。

またはzshbash

dirs=(*/)
mkdir -- "${dirs[@]/%/doc}"
touch -- "${dirs[@]/%/doc/doc1.txt}"

${var/pattern/replace}Korn シェルの代替演算子に似ています。の場合、${array[@]/pattern/replace}配列の各要素に適用されます。%これは意味する最後に

さまざまな考慮事項:

dirs=(*/)[ -L "$file" ]ディレクトリとディレクトリへのシンボリックリンクを含めます(ループで使用されている場合を除き、シンボリックリンクを除外する方法はありません)。一方dir=(*(/))(zsh拡張子)はディレクトリのみを含みます(dir=(*(-/))末尾のスラッシュを追加せずにディレクトリへのシンボリックリンクを含む)。

隠しディレクトリは除外されます。各シェルには、隠しファイルを含めるための特定のオプションがあります。

現在のディレクトリに他の人が書き込める場合は、セキュリティの問題が発生する可能性があります。人々はそこにシンボリックリンクを作成し、望ましくないディレクトリやファイルを作成できるからです。シンボリックリンクを考慮しないソリューションを使用しても、ディレクトリを間dirs=(*/)のシンボリックリンクに置き換えることができるため、まだ競合状態がありますmkdir...

答え3

for d in /*/
do  [ -d "$d" ] || break
    f=$d/docs/doc1.txt    
    mkdir -p -- "${f%/*}"
    touch -- "$f"
done

私はそれがあなたの目標に適していると思います。たぶん私は何かを逃したようです。

それ以外の場合は、次のことができます。

set -- /*/
[ -d "$1" ] && 
printf 'd=$%d
    mkdir -p -- "$d/docs" && 
    touch -- "$d/docs/doc1.txt"
' $(seq "$#") | sh -s -- "$@"

または:

set -- /*/
while [ -d "$1" ] 
do  mkdir -p -- "$1"/docs
    touch -- "$1"/docs/doc1.txt
shift ; done

答え4

わかりました。短い:

ls -1|xargs -i% bash -c 'mkdir %/doc;>>%/doc/doc1.txt'


- 私たちはあなたと同じディレクトリにいます起動ディレクトリ

  • ls -1リスト1つなどherdir、1行に1つずつ(他はない)

  • xargスクリプト引数を使用してシェルを実行し、%をディレクトリに置き換えます。

  • 各ディレクトリに対して、次の操作を行います。

    • bash2つのコマンドを含む1つの文字列引数を使用してシェルスクリプトとして実行します。

      • mkdir %/docディレクトリの作成
      • >>%/doc/doc1.txt空のファイルの作成2


$ ls
$ mkdir mydir hisdir herdir
$ ls                       
herdir  hisdir  mydir
$ ls -1|xargs -i% bash -c 'mkdir %/doc;>>%/doc/doc1.txt'
$ find
.
./herdir
./herdir/doc
./herdir/doc/doc1.txt
./hisdir
./hisdir/doc
./hisdir/doc/doc1.txt
./mydir
./mydir/doc
./mydir/doc/doc1.txt



1)芸術的自由;探す。 -最大深さ1 -タイプd

2)>>fileここでtouchと同様に空のファイルを作成します。詳細については、bash次を参照してください。man bash、キー/を使って「出力リダイレクト」を検索します。

関連情報