
/
多くのディレクトリを含むディレクトリがあり、/mydir
各ディレクトリは同様の構造を持つ必要があるとします。/hisdir
/herdir
各ディレクトリにはディレクトリとその中にファイルが/
含まれている必要があります。doc
doc1.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
ここでelt1
、elt2
はelt3
配列の要素です)。
次のようにすることもできます。
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
引用符特定の文字の問題を防ぐ単語です。
またはzsh
:bash
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
スクリプト引数を使用してシェルを実行し、%をディレクトリに置き換えます。各ディレクトリに対して、次の操作を行います。
bash
2つのコマンドを含む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、キー/を使って「出力リダイレクト」を検索します。