Bagaimana cara membuat direktori di semua subdirektori?

34

Misalkan saya memiliki struktur direktori seperti ini:

$ [~ / latihan] ls
a / b / c / d /

Sekarang saya ingin membuat direktori tmp1di semua sub direktori practicedan saya melakukan ini:

$ [~ / practice] mkdir * / tmp1
mkdir: tidak dapat membuat direktori `* / tmp1 ': Tidak ada file atau direktori tersebut

Lalu saya coba -psakelar dan saya akhiri dengan direktori yang dinamai *dengan sub direktoritmp1

$ [~ / practice] mkdir -p * / tmp1

$ [~ / latihan] ls
* / a / b / c / d /

Saya tahu penggunaan -pswitch adalah untuk membuat beberapa direktori yang tidak ada. Saya hanya berpikir itu mungkin membantu.

Bagaimana cara saya membuat tmp1di semua subdirektori sekaligus?

Jika ini bisa dilakukan, bagaimana cara memperpanjang untuk membuat \tmp1, \tmp2, \tmp3di \a, \bdan \csekaligus?

Edit: Aku rindu menyebutkan bahwa direktori tidak harus sederhana dan dalam rangka, seperti a, b, cdll, dan direktori yang akan dibuat belum tentu seperti tmp1, tmp2.

$ [~ / latihan] ls
anjing / kucing / tikus /

Di dalamnya, saya ingin memiliki sesuatu seperti

$ [~ / latihan] ls *
anjing:
merah biru/

kucing:
merah biru/

tikus:
merah biru/
Animesh
sumber
1
Dengan jawaban Christopher , Anda harus mengklarifikasi apakah "create \ tmp1, \ tmp2, \ tmp3 dalam \ a, \ b dan \ c" akan menghasilkan total 3 atau 9 subdirektori.
manatwork
@Manatwork: Itu poin yang bagus. Itu harus membuat 9 subdirektori.
Animesh
Ini bantuan saya untuk memecahkan masalah ruang atas nama direktori sudo find ./ -depth -type d -exec echo '"{} / RCS"' \;

Jawaban:

44

Dengan gumpalan :

for dir in */; do mkdir -- "$dir/tmp1"; done

CATATAN

  • Saya hanya memperlakukan dir (termasuk symlink ke dir) dengan sedikit hack menggunakan */sebagai glob
  • Jika Anda ingin membuat beberapa subdir sekaligus:

    for dir in */; do mkdir -- "$dir"/{tmp1,foo,bar,qux}; done

Gilles Quenot
sumber
Bisakah saya melakukan for i in */; do mkdir "$i/itemone" "$i/itemtwo"; donebeberapa nama direktori yang tidak berurutan?
Animesh
Saya menguji ini dan itu sangat mungkin. Terima kasih.
Animesh
Lihat posting saya yang diedit
Gilles Quenot
1
Ekspansi brace tidak dilakukan dalam string yang dikutip.
manatwork
Ya, terima kasih, pos diedit oleh Stephane Chazelas sesuai ...
Gilles Quenot
10

[...] bagaimana saya memperluasnya untuk membuat \ tmp1, \ tmp2, \ tmp3 dalam \ a, \ b dan \ c sekaligus?

 mkdir {a,b,c}/tmp{1,2,3}
Christopher
sumber
10

Dengan GNU atau BSD * temukan:

find -mindepth 1 -maxdepth 1 -type d -exec mkdir {}/newdir \;

atau menggunakan ekspansi parameter:

dirs=(*/)
mkdir -- "${dirs[@]/%/newdir}"

* Termasuk OS X

kojiro
sumber
2
Dengan sintaks find standar:find . -name . -o -prune -type d -exec sh -c 'exec mkdir "$1/newdir"' sh {} \;
Stéphane Chazelas
1
Perhatikan juga perbedaan antara dua solusi: yang pertama termasuk direktori tersembunyi, yang kedua akan menambahkan baru di direktori yang ditautkan oleh setiap symlink di direktori saat ini.
Stéphane Chazelas
6

Di luar topik karena Anda sebutkan bash, tetapi sebagai catatan, dengan zsh, Anda akan melakukannya:

dirs=(*(/))
mkdir -- $^dirs/tmp1

$^varmengaktifkan ekspansi brace-like untuk ekspansi array. Ini mengingatkan rc's ^operator dan dalam rc(atau turunannya es), Anda akan menulis itu:

dirs=(*/)
mkdir -- $dirs^tmp1

Namun perhatikan (dan hal yang sama berlaku untuk solusi bash yang diberikan di sini) bahwa dalam solusi rc dirsjuga akan berisi tautan simbolis ke direktori. Dalam solusi zsh, ubah *(/)ke *(-/)jika Anda ingin menyertakan symlink ke direktori.

Stéphane Chazelas
sumber
+1 untuk poin Anda tentang symlink! Perilaku ini mungkin diinginkan, tetapi keluhan mkdir tentang membuat direktori duplikat dapat ditekan dengan -pbendera.
kojiro
4

Mudah dibawa, putar di atas direktori induk:

for d in */; do mkdir "$d/red" "$d/blue"; done

Tambahkan --setelah mkdirjika Anda memiliki direktori yang namanya dimulai -.

Di zsh, Anda dapat melakukannya dalam satu perintah dengan e kualifikasi glob :

mkdir *(/e\''REPLY=($REPLY/{red,blue})'\')

tetapi lebih cepat untuk mengetik ini sebagai dua perintah:

d=(*(/)); mkdir $^d/{red,blue}
Gilles 'SANGAT berhenti menjadi jahat'
sumber
1
Di situs yang dimaksudkan sebagai referensi, saya lebih suka mengatakan " mkdir -- whatever, dan mengabaikan -- jika Anda berniat untuk memperluas apa pun yang mungkin diambil sebagai opsi untuk mkdirperintah.". Tidak ada gunanya menghilangkan di --sini. Ini mungkin bukan masalah dalam kasus OP, tapi itu adalah masalah umum. Saya pikir kita memiliki kewajiban untuk mengajarkan sintaks yang benar dan aman di sini.
Stéphane Chazelas
@StephaneChazelas Dalam konteks penulisan skrip, saya selalu menaruh semua yang diperlukan --dan mengutip serta peringatan besar ketika baris baru tidak didukung. Dalam konteks baris perintah, saya lebih suka menampilkan versi cepat yang berfungsi pada praktiknya terlebih dahulu, dan versi antipeluru sebagai pelengkap.
Gilles 'SO- berhenti bersikap jahat'
1

Anda dapat melakukannya seperti itu:

mkdir {a,b,c,d}/tmp1
ДМИТРИЙ МАЛИКОВ
sumber
1
Bagaimana jika dia memiliki 100 direktori?
Bernhard
1

Variasi pada jawaban sputnick yang menghindari file non-direktori:

for x in *; do if [ -d "$x" ]; then mkdir "$x/tmp1"; fi; done
goldilocks
sumber
Saya hanya memperlakukan dir, itu saja keajaiban ...
Gilles Quenot
keren, mengerti;)
goldilocks
2
Bukankah seharusnya begitu if [ -d "$x" ];…?
kojiro
Iya nih. Saya praktis tidak pernah memiliki spasi dalam nama file dan cenderung melupakan hal-hal itu ...
goldilocks
1

Ini adalah versi yang bagus dari Unix Masters lama (diuji pada FreeBSD 10.1) jika Anda ingin mengontrol versi (dengan RCS check in terkunci: ci-l dengan komentar singkat sebagai ir: untuk rilis awal) file konfigurasi / etc / * config Anda pada ~ / .ini / etc

sudo rsync -av /etc/ ~/.his
sudo find -d ~/.his/etc -type d -exec echo '{}/RCS' \; | xargs sudo mkdir -p
sudo find -d ~/.his/etc \! -name "RCS" | xargs sudo ci -l -mir -t-ir
pengguna108341
sumber
Saya gagal melihat bagaimana ini menjawab OP
Archemar
1

Seharusnya \! beri nama "RCS" dan berfungsi paling baik pada saat check-in pertama.

sudo find ~ / .his / etc \! -nama "RCS" -l

sudo find -d ~ / .his / etc \! -nama "RCS" | xargs sudo ci -l -mir -t-ir

Yang terakhir ini juga berfungsi dengan baik untuk cjeck di bagian memfilter semua konten RCS pada nama file:

sudo find -d ~ / .his / etc -type f | grep -v RCS | xargs sudo ci -l -mir -t-ir

pengguna108341
sumber
1

ini sangat membantu saya. saya harus membuat satu set subdirektori dalam beberapa folder dan sesuatu seperti:

!/bin/sh

cd /dest/cont

for dir in */*/; do
    mkdir -p -- $dir/{FB,Video,Audio,proj};
done

bekerja sangat baik kecuali ketika ruang putih ditemukan. adakah cara untuk mengabaikan ruang di */*/bagian argumen?

johno
sumber