mkdir -p untuk file

24

mkdir -pakan membuat direktori; itu juga akan membuat direktori induk sesuai kebutuhan.

Apakah ada perintah yang serupa untuk file, yang akan membuat file dan direktori induk sesuai kebutuhan?

Steven Penny
sumber
Bukannya saya sadar .. tetapi Anda hanya bisa melakukan mkdir -p / path / to / make && touch / path / to / file ... Yang mana akan membuat file kosong dalam struktur direktori baru yang Anda buat semua sesuai kebutuhan.
1
@Kansha menggabungkannya dengan dirnamedan basenamedan kita hanya perlu argumen tunggal; keuntungan! :)
Ya, panggilan yang bagus.

Jawaban:

29

Instal akan melakukan ini, jika diberi file sumber /dev/null. The -Dargumen mengatakan untuk membuat semua direktori induk:

anthony@Zia:~$ install -D /dev/null /tmp/a/b/c
anthony@Zia:~$ ls -l /tmp/a/b/c 
-rwxr-xr-x 1 anthony anthony 0 Jan 30 10:31 /tmp/a/b/c

Tidak yakin apakah itu bug atau tidak — perilakunya dengan file perangkat tidak disebutkan dalam manual. Anda juga bisa memberikannya file kosong (baru dibuat dengan mktemp, misalnya) sebagai sumber.

derobert
sumber
7

Tidak, tidak sejauh yang saya tahu. Tetapi Anda selalu dapat menggunakan mkdir -pdan touchsaling berhadapan:

f="/a/b/c.txt"
mkdir -p -- "${f%/*}" && touch -- "$f"
ldx
sumber
3

Saya sering mengalami situasi seperti ini, jadi saya hanya menulis fungsi di .bashrcfile saya . Ini terlihat seperti ini

function create() {
    arg=$1
    num_of_dirs=$(grep -o "/" <<< $arg | wc -l)
    make_dirs=$(echo $arg | cut -d / -f1-$num_of_dirs)
    mkdir -p $make_dirs && touch $arg
}

Jadi, ketika saya ingin membuat file di dalam jalur direktori yang tidak ada, saya akan mengatakan

create what/is/it  # will create dirs 'what' and 'is', with file 'it' inside 'is'
ViKiG
sumber
1
Lelaki ku! - terima kasih, saya menyebutnya touchp, sepertimkdir -p
ecoologic
0
dir=$(dirname "$f")
test -d $dir || mkdir -p "$dir"
Yordan Georgiev
sumber
3
Tidak testdiperlukan; mkdir -ptidak melakukan apa-apa jika direktori sudah ada. Bahkan tidak mengembalikan kesalahan.
derobert
1
Dan tentu saja, ini hanya membuat direktori.
CVn
0

Saya akan menyarankan karena tetap pada satu baris, meskipun pengaturan variabel secara terpisah memungkinkan Anda untuk mengubahnya dan jalankan kembali perintah dari sejarah dengan mudah.

B="./make/this/path" && mkdir -p -- "$B" && touch -- "$B/file.txt"
Gilles 'SANGAT berhenti menjadi jahat'
sumber
0

Dimungkinkan untuk "berpura-pura".

Pertama, beberapa teori yang dibutuhkan:

Rob Griffiths memposting sebuah artikel pada tahun 2007 berjudul Mudah Membuat Banyak Folder Baru di Macworld.com di mana ia berdiskusi menggunakan xargsperintah untuk membaca dalam daftar file untuk membuat direktori menggunakan mkdir.

xargsmampu mereferensikan a placeholder( {}) dengan -Iflag, yang berisi nilai untuk setiap argumen yang diteruskan xargs. Inilah perbedaan antara dengan bendera itu, dan tanpa:

$ foo.txt bar.txt | xargs echo
$ => foo.txt bar.txt
$ foo.txt bar.txt | xargs -I {} echo {}
$ => foo.txt
$ => bar.txt

xargsjuga mampu menjalankan perintah shell sewenang-wenang dengan sh -cbendera:

foo.txt bar.txt | xargs sh -c 'echo arbitrary command!'

Menggabungkan Konsep:

Kita bisa menggabungkan konsep-konsep ini dengan mkdir -pbukannya mkdirdan konsep di @ldx 's jawaban untuk menghasilkan ini:

$ cat files.txt | xargs -I {} sh -c 'f="{}" && mkdir -p -- "${f%/*}" && touch -- "$f"'

Perintah ini pada dasarnya memetakan setiap nama file dalam daftar file yang dipisahkan baris, memotong bagian file, membuat direktori dengan mkdir -pdan kemudian touchnama file di direktori masing-masing.

Berikut ini rincian dari apa yang terjadi pada perintah di atas:

Katakan misalnya files.txtpenampilan saya seperti ini:

deeply/nested/foo/bar.txt
deeply/nested/baz/fiz.txt
  • cat files.txt menghasilkan deeply/nested/foo/bar.js deeply/nested/baz/fiz.txt
  • deeply/nested/foo/bar.js deeply/nested/baz/fiz.txt disalurkan ke xargs
  • karena kita menggunakan -I {}, xargsakan menerjemahkan setiap argumen ke perintah itu sendiri, jadi sekarang kita memiliki:
    • deeply/nested/foo/bar.txt
    • deeply/nested/baz/fiz.txt
  • kami kemudian menjalankan perintah shell yang menggunakan &&combinator untuk mengelompokkan 3 perintah yang berjalan secara berurutan - perintah pertama menyimpan file dalam variabel lingkungan (yang akan digunakan kembali pada file berikutnya) menggunakan placeholder yang telah kami daftarkan sebelumnya, jadi kami sekarang memiliki:
    • f=deeply/nested/foo/bar.txt
    • f=deeply/nested/baz/fiz.txt
  • kita sekarang memiliki variabel yang bisa kita lewati mkdir -p, tetapi kita perlu memotong nama file. Cukup sederhana menggunakan '${f%/*}':
    • mkdir -p deeply/nested/foo/
    • mkdir -p deeply/nested/baz/
  • dan kemudian kita hanya mereferensikan fvariabel secara keseluruhan ketika kita touch:
    • touch deeply/nested/foo/bar.txt
    • touch deeply/nested/baz/fiz.txt
Razorbeard
sumber
2
Anda memiliki semua penjelasan ini untuk apa yang pada dasarnya cat files.txt | xargs -I {} sh -c 'f="{}" && mkdir -p -- "${f%/*}" && touch -- "$f"', yang memiliki UUOC, kemudian Anda subshell menjadi xargs yang subshell kembali ke shell, ketika sebuah while readloop lebih masuk akal
Steven Penny
1
Saya akui saya bukan yang paling tahu tentang perintah * nix - saya bahkan tidak tahu apa itu UUOC - tapi saya gagal melihat bagaimana ini adalah jawaban yang buruk. Itu sedang diteliti, diuji dan merupakan solusi untuk pertanyaan awal Anda. Itu konstruktif (tidak seperti komentar Anda yang agak kasar). Tolong, jika Anda merasa bahwa saya telah melakukan sesuatu yang tidak bertanggung jawab di sini yang seharusnya tidak saya lakukan, maka uraikan lebih lanjut - jelaskan alasannya . Saya tidak terlalu peduli dengan perdebatan pendapat yang tidak memiliki substansi.
razorbeard
1
Komentar terakhir saya menjelaskannya dengan sempurna. Seluruh jawaban Anda bisa ditulis dengan lebih baik while read f; do mkdir -p "$(dirname "$f")"; touch "$f"; done < files.txt. Fakta bahwa Anda tidak dapat melakukan pencarian internet 10 detik untuk UUOC juga memberi tahu
Steven Penny