Unix - klasörlerin ve dosyanın yolunu oluşturun


126

mkdirBir dizin oluşturmak ve touchbir dosya oluşturmak için yapabileceğinizi biliyorum , ancak her iki işlemi tek seferde yapmanın bir yolu yok mu?

yani, klasör yokken aşağıdakileri yapmak istersem other:

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

Hata:

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

Bunun için geçici çözüm olarak bir işlev bulan var mı?



Dosyanın ve dizininin oluşturulmasının atomik olması önemliyse, bu işlemi sunan bir dosya sistemi yazmanız gerekir. Standart Linux dosya sistemleriyle mümkün değildir.
Peter G.

@toop Bu sorunun şu anda bir buçuk yaşında olduğunu anlıyorum, ancak yakın zamanda birkaç cevap bununla birleştirildi. Bu tür şeylere çok sık ihtiyaç duyuyorsanız, cevabımı faydalı bulabilirsiniz . (Kabul edilen cevaptan daha yararlı olduğunu iddia ederdim, ancak burada tekrar için yalvarmıyorum :-))
Jonathon Reinhart


@tdammers S: "X'i nasıl yaparım?" C: "Y'nin nasıl yapılacağı burada"
Henry Henrinson

Yanıtlar:


140

&&İki komutu bir kabuk satırında birleştirmek için kullanın :

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

Not: Daha önce ;iki komutu ayırmak için öğesinin kullanılmasını tavsiye etmiştim , ancak @trysis'in işaret ettiği gibi &&, çoğu durumda kullanmak muhtemelen daha iyidir çünkü COMMAND1başarısızlık durumunda COMMAND2da çalıştırılmayacaktır. (Aksi takdirde, bu beklemediğiniz sorunlara yol açabilir.)


16
Muhtemelen &&, olduğu gibi, kullanılması daha iyidir ;, eğer ilk komut başarısız olursa, ikinci komut yine de çalışacaktır (ve o dizin henüz mevcut olmadığı için de başarısız olacaktır). İle &&ilk komutu başarısız olursa, ikinci komutu çalışmaz.
trysis

12
Kod, örneğin bir kısa kesilmiş olabilir: mkdir -p /my/other/path/here && touch $_/cpredthing.txt. $_Esasen için genişlediğinde "Son komuta son argüman infaz".
Sgnl

4
@Sgnl senin muhtemelen doğru cevap. Sadece daha temiz değil, hataya daha az meyillidir.
Choylton B. Higginbottom

3
Keşke yaptığı gibi touchbir -pparametre mkdiralsın.
Ben174

86

Önce tüm ana dizinleri yapmanız gerekir.

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

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

Yaratıcı olmak istiyorsanız, bir işlev yapabilirsiniz :

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

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

Ve sonra onu herhangi bir komut gibi kullanın:

mktouch ./base/data/sounds/effects/camera_click.ogg ./some/other/file

Kullanmak için değiştirildi &&- Bu nasıl?
Jonathon Reinhart

1
@ BЈовић Evet . (Bir şeyleri göndermeden önce test etmeye çalışıyorum.)
Jonathon Reinhart

2
@JonathonReinhart Test ettiğinizden emin misiniz? Denedim supertouch "/tmp/abc/def ghi/jkl mno.txt"ve başarısız oldu. Tüm komutlar dirname, mkdirve touchhatalara verdi.
devnull

2
@devnull Görünüşe göre yeterince iyi değil. Boşluklarınıza lanet olsun :-) Düzeltildi.
Jonathon Reinhart

1
@JeremyIglehart Bunu beğendim. mktouchbu.
Jonathon Reinhart

24

Bunu / usr / bin / install ile yapın:

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

kaynak dosyanız yoksa:

install -D <(echo 1) /my/other/path/here/cpedthing.txt

1
Bu mücevher aracının büyük ölçüde göz ardı edilmesine şaşırdım - adam kurulumu - kurulumun daha iyi bir çözüm olduğunu gösterecek.
SC-SL

1
Ayrıca kullanabilirsin -D /dev/null, bu benim için hatırlaması daha kolay.
bilgece

14

Yapacağım şey bu:

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

Burada, $_satırda çalıştırdığımız önceki komutun son argümanını temsil eden bir değişkendir.

Her zaman olduğu gibi, çıktının ne olabileceğini görmek istiyorsanız echo, aşağıdaki gibi komutu kullanarak test edebilirsiniz :

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

Hangi çıktılar:

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

Bonus olarak, ayraç genişletmeyi kullanarak aynı anda birden fazla dosya yazabilirsiniz, örneğin:

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

Yine, şunlarla tamamen test edilebilir 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

13
#!/bin/sh
for f in "$@"; do mkdir -p "$(dirname "$f")"; done
touch "$@"

1
Anonim bir kullanıcı dirname -z "$@" | xargs -0 mkdir -p, performans uğruna bunun yerine kullanılmasını önerdi (düzenleme yoluyla) . (
Gizlenmeyi

11

bunu iki adımda yapabilirsiniz:

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

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

2

Bir unix forumunda gördüğüm ve test ettiğim gibi, bu sorunu çözüyor

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

1

if thenaçıklamaya gerek yok ... bunu tek satırda yapabilirsiniz usign;

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

- veya iki satırda -

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

- -pdizin zaten mevcutsa hata geri dönüşlerini engeller (buraya aradığım şey bu :))


1

Aynı dizin hiyerarşisini yeniden oluşturmaya çalıştığınız özel (ancak nadir olmayan) durumda cp --parentsfaydalı olabilir.

Örneğin /my/long, kaynak dosyaları içeriyorsa ve my/otherzaten varsa, bunu yapabilirsiniz:

cd /my/long
cp --parents path/here/thing.txt /my/other

-4

sadece 1 param pasajı ile basit istiyorsanız:

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

3
Son birkaç saatlik çalışmadan kurtulmak istiyorsanız, minnettarlıkla bazı rm -rfkomutlar verin. - †Yani, mantıklı bir sürüm kontrol / yedekleme politikasına bağlı kaldığınızı varsayarsak saatler ... aksi halde aylar sürebilir .
leftaroundabout

1
rm -rf uygun açıklama ve uyarılar olmadan asla önerilmemelidir.
Mausy5043
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.