Unix - buat jalur folder dan file

126

Saya tahu Anda dapat melakukannya mkdiruntuk membuat direktori dan touchmembuat file, tetapi apakah tidak ada cara untuk melakukan kedua operasi sekaligus?

yaitu jika saya ingin melakukan hal di bawah ini ketika folder othertidak ada:

cp /my/long/path/here/thing.txt /my/other/path/here/cpedthing.txt

Kesalahan:

cp: cannot create regular file `/my/other/path/here/cpedthing.txt': No such file or directory

Adakah yang datang dengan fungsi sebagai solusi untuk ini?

toop
sumber
1
Ditemukan ini: stackoverflow.com/questions/1529946/…
Bjørne Malmanger
Jika penting bahwa pembuatan file dan direktorinya bersifat atomik, Anda harus menulis sistem file yang menawarkan operasi ini. Ini tidak mungkin dengan sistem file Linux standar.
Peter G.
@toop Saya memahami bahwa pertanyaan ini sekarang sudah berumur satu setengah tahun, tetapi beberapa jawaban baru-baru ini digabungkan menjadi pertanyaan ini. Jika Anda sangat membutuhkan hal semacam ini, Anda mungkin menemukan jawaban saya berguna. (Saya berpendapat lebih bermanfaat daripada jawaban yang diterima, tapi saya tidak memohon perwakilan di sini :-))
Jonathon Reinhart
Ditemukan ini: stackoverflow.com/a/8722721/29182
Ziggy
@tdammers T: "Bagaimana saya melakukan X?" J: "Inilah cara melakukan Y"
Henry Henrinson

Jawaban:

140

Gunakan &&untuk menggabungkan dua perintah dalam satu baris shell:

COMMAND1 && COMMAND2
mkdir -p /my/other/path/here/ && touch /my/other/path/here/cpedthing.txt

Catatan: Sebelumnya saya merekomendasikan penggunaan ;untuk memisahkan dua perintah tetapi seperti yang ditunjukkan oleh @trysis mungkin lebih baik digunakan &&dalam banyak situasi karena jika COMMAND1gagal COMMAND2tidak akan dijalankan juga. (Jika tidak, ini dapat menyebabkan masalah yang mungkin tidak Anda duga.)

evotopid
sumber
16
Mungkin lebih baik digunakan &&, seperti halnya ;, jika perintah pertama gagal, perintah kedua akan tetap berjalan (dan juga gagal, karena direktori itu belum ada). Dengan &&jika perintah pertama gagal, maka perintah kedua tidak berjalan.
trisis
12
Sebuah jalan pintas untuk contoh kode dapat: mkdir -p /my/other/path/here && touch $_/cpredthing.txt. Pada $_dasarnya diperluas menjadi "argumen terakhir dalam perintah terakhir yang dijalankan".
Sgnl
4
@Sgnl milikmu bisa dibilang jawaban yang benar. Ini tidak hanya lebih bersih, tetapi juga tidak terlalu rentan terhadap kesalahan.
Choylton B. Higginbottom
3
Saya benar-benar berharap touchmengambil -pparameter seperti mkdiritu.
Ben174
86

Anda harus membuat semua direktori induk terlebih dahulu.

FILE=./base/data/sounds/effects/camera_click.ogg

mkdir -p "$(dirname "$FILE")" && touch "$FILE"

Jika ingin berkreasi, Anda bisa membuat fungsi :

mktouch() {
    if [ $# -lt 1 ]; then
        echo "Missing argument";
        return 1;
    fi

    for f in "$@"; do
        mkdir -p -- "$(dirname -- "$f")"
        touch -- "$f"
    done
}

Dan kemudian gunakan seperti perintah lainnya:

mktouch ./base/data/sounds/effects/camera_click.ogg ./some/other/file
Jonathon Reinhart
sumber
Berubah untuk digunakan &&- Bagaimana?
Jonathon Reinhart
1
@ BЈовић Ya . (Saya mencoba untuk menguji beberapa hal sebelum saya mempostingnya.)
Jonathon Reinhart
2
@JonathonReinhart Apakah Anda yakin telah mengujinya? Saya mencoba supertouch "/tmp/abc/def ghi/jkl mno.txt"dan gagal. Semua perintah dirname, mkdirdan touchmemberikan erros.
devnull
2
@devnull Rupanya kurang sehat. Sialan spasi Anda :-) Tetap.
Jonathon Reinhart
1
@JeremyIglehart Saya menyukainya. mktouchini.
Jonathon Reinhart
24

Lakukan dengan / usr / bin / install:

install -D /my/long/path/here/thing.txt /my/other/path/here/cpedthing.txt

ketika Anda tidak memiliki file sumber:

install -D <(echo 1) /my/other/path/here/cpedthing.txt
Ivan Dives
sumber
1
Saya terkejut alat permata ini sebagian besar diabaikan - man install - akan menunjukkan bahwa menginstal adalah solusi yang lebih baik.
SC-SL
1
Anda juga bisa menggunakan -D /dev/null, yang lebih mudah saya ingat.
wisbucky
14

Inilah yang akan saya lakukan:

mkdir -p /my/other/path/here && touch $_/cpredthing.txt

Di sini, $_adalah variabel yang mewakili argumen terakhir ke perintah sebelumnya yang kita jalankan sejalan.

Seperti biasa jika Anda ingin melihat seperti apa hasilnya, Anda dapat mengujinya dengan menggunakan echoperintah, seperti:

echo mkdir -p /code/temp/other/path/here && echo touch $_/cpredthing.txt

Output mana sebagai:

mkdir -p /code/temp/other/path/here
touch /code/temp/other/path/here/cpredthing.txt

Sebagai bonus, Anda dapat menulis banyak file sekaligus menggunakan brace expansion, misalnya:

mkdir -p /code/temp/other/path/here &&
touch $_/{cpredthing.txt,anotherfile,somescript.sh}

Sekali lagi, benar-benar dapat diuji dengan echo:

mkdir -p /code/temp/other/path/here
touch /code/temp/other/path/here/cpredthing.txt /code/temp/other/path/here/anotherfile /code/temp/other/path/here/somescript.sh
Sgnl
sumber
13
#!/bin/sh
for f in "$@"; do mkdir -p "$(dirname "$f")"; done
touch "$@"
Javier
sumber
1
Seorang pengguna anonim menyarankan (melalui edit) untuk digunakan dirname -z "$@" | xargs -0 mkdir -psebagai gantinya, demi kinerja. (Berhenti mengintai, dan bergabunglah, demi Pete! ;-)
jpaugh
11

Anda dapat melakukannya dalam dua langkah:

mkdir -p /my/other/path/here/
touch /my/other/path/here/cpedthing.txt
Jörg Beyer
sumber
2
if [ ! -d /my/other ]
then
   mkdir /my/other/path/here
   cp /my/long/path/here/thing.txt /my/other/path/here/cpedthing.txt
fi
Barun Parichha
sumber
2

seperti yang saya lihat dan uji di forum unix, ini memecahkan masalah

ptouch() {
    for p in "$@"; do
        _dir="$(dirname -- "$p")"
        [ -d "$_dir" ] || mkdir -p -- "$_dir"
    touch -- "$p"
    done
}
Fabian Rios
sumber
1

tidak perlu if thenpernyataan ... Anda dapat melakukannya pada satu baris usign;

mkdir -p /my/other/path/here;cp /my/long/path/here/thing.txt /my/other/path/here/cpedthing.txt

- atau dalam dua baris -

mkdir -p /my/other/path/here
cp /my/long/path/here/thing.txt /my/other/path/here/cpedthing.txt

- -pkesalahan pencegahan kembali jika direktori sudah ada (yang saya datang ke sini mencari :))

tediffer3rd
sumber
1

Dalam kasus khusus (tetapi tidak jarang) di mana Anda mencoba membuat ulang hierarki direktori yang sama, cp --parentsbisa berguna.

Misalnya jika /my/longberisi file sumber, dan my/othersudah ada, Anda dapat melakukan ini:

cd /my/long
cp --parents path/here/thing.txt /my/other
Todd Owen
sumber
-4

kalau mau simple dengan hanya 1 param snippet:

rm -rf /abs/path/to/file;  #prevent cases when old file was a folder
mkdir -p /abs/path/to/file; #make it fist as a dir
rm -rf /abs/path/to/file; #remove the leaf of the dir preserving parents 
touch /abs/path/to/file; #create the actual file
orang asing
sumber
3
Jika Anda hanya ingin menyingkirkan pekerjaan beberapa jam terakhir, berikan beberapa rm -rfperintah dengan bersyukur . - † Artinya, berjam-jam , dengan asumsi Anda mematuhi kebijakan kontrol / cadangan versi yang masuk akal ... jika tidak, mungkin akan memakan waktu berbulan-bulan.
kiri sekitar sekitar
1
rm -rftidak boleh disarankan tanpa penjelasan dan peringatan yang tepat.
Mausy5043