mkdir -p per i file


24

mkdir -pcreerà una directory; creerà anche le directory principali secondo necessità.

Esiste un comando simile per i file, che creerà un file e le directory principali secondo necessità?


Non che io sia a conoscenza di ... ma potresti semplicemente fare mkdir -p / path / to / make && touch / path / to / file ... Il che renderebbe un file vuoto in quella nuova struttura di directory che hai creato tutto come necessario.

1
@Kansha lo combina con dirnamee basenamee avremo solo bisogno del singolo argomento; profitto! :)

Sì, buona chiamata.

Risposte:


29

L'installazione eseguirà questa operazione, se fornito il file di origine /dev/null. L' -Dargomento dice di creare tutte le directory principali:

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

Non sono sicuro che si tratti di un bug o meno: il suo comportamento con i file del dispositivo non è menzionato nella manpage. Potresti anche dargli un file vuoto (appena creato con mktemp, ad esempio) come sorgente.


7

No, per quanto ne so. Ma puoi sempre usare mkdir -pe touchdopo l'altro:

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

3

Mi sono imbattuto spesso in questo tipo di situazione, quindi ho semplicemente scritto una funzione nel mio .bashrcfile. Sembra così

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
}

Quindi, quando voglio creare un file all'interno di un percorso di directory inesistenti, lo dirò

create what/is/it  # will create dirs 'what' and 'is', with file 'it' inside 'is'

1
Il mio uomo! - grazie, l'ho chiamato touchp, tipomkdir -p
ecologico

0
dir=$(dirname "$f")
test -d $dir || mkdir -p "$dir"

3
Non testè necessario; mkdir -pnon fa nulla se la directory esiste già. Non restituisce nemmeno un errore.
derobert,

1
E, naturalmente, questo crea solo la directory.
un CVn

0

Stavo per suggerire che la mantiene su una riga, sebbene l'impostazione della variabile separatamente ti permetta di cambiarla e rieseguire il comando dalla cronologia abbastanza facilmente.

B="./make/this/path" && mkdir -p -- "$B" && touch -- "$B/file.txt"

0

È possibile "fingere".

Innanzitutto, alcune teorie richieste:

Rob Griffiths ha pubblicato un articolo nel 2007 intitolato Creare facilmente molte nuove cartelle su Macworld.com in cui ha discusso usando il xargscomando per leggere un elenco di file per creare directory usandomkdir .

xargsè in grado di fare riferimento a a placeholder( {}) con il -Iflag, che contiene il valore per ogni argomento passato a xargs. Ecco la differenza tra con quella bandiera e senza:

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

xargsè anche in grado di eseguire comandi di shell arbitrari con il sh -cflag:

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

Combinare i concetti:

Siamo in grado di combinare questi concetti con mkdir -pal posto del mkdire il concetto in @ldx 's risposta per produrre questo:

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

Questo comando fondamentalmente mappa ogni nome di file in un elenco di file separato da linee, taglia la parte del file, crea le directory con mkdir -pe poitouch es il nome del file nella rispettiva directory.

Ecco una ripartizione di ciò che accade nel comando sopra:

Di 'ad esempio il mio files.txtaspetto simile al seguente:

deeply/nested/foo/bar.txt
deeply/nested/baz/fiz.txt
  • cat files.txt produce deeply/nested/foo/bar.js deeply/nested/baz/fiz.txt
  • deeply/nested/foo/bar.js deeply/nested/baz/fiz.txt viene convogliato a xargs
  • poiché abbiamo usato -I {}, xargstraduciamo ogni argomento nel suo comando, quindi ora abbiamo:
    • deeply/nested/foo/bar.txt
    • deeply/nested/baz/fiz.txt
  • eseguiamo quindi un comando shell che utilizza il &&combinatore per raggruppare 3 comandi eseguiti in sequenza: il primo comando memorizza il file in una variabile di ambiente (che viene riutilizzato al successivo passaggio di file) utilizzando il segnaposto che abbiamo registrato in precedenza, quindi ora avere:
    • f=deeply/nested/foo/bar.txt
    • f=deeply/nested/baz/fiz.txt
  • ora abbiamo una variabile a cui possiamo passare mkdir -p, ma dobbiamo tagliare il nome del file. Abbastanza semplice usando '${f%/*}':
    • mkdir -p deeply/nested/foo/
    • mkdir -p deeply/nested/baz/
  • e quindi ri-referenziamo la fvariabile nella sua interezza quando touch:
    • touch deeply/nested/foo/bar.txt
    • touch deeply/nested/baz/fiz.txt

2
Hai tutta questa spiegazione per ciò che è essenzialmente cat files.txt | xargs -I {} sh -c 'f="{}" && mkdir -p -- "${f%/*}" && touch -- "$f"', che ha UUOC, quindi ti sottrai a xargs che ricadono nella shell, quando un while readciclo ha più senso
Steven Penny

1
Devo ammettere che non sono il più informato sui comandi * nix - non so nemmeno cosa sia UUOC - ma non riesco a vedere come questa sia una risposta terribile. È studiato, testato ed è una soluzione funzionante alla tua domanda originale. È costruttivo (a differenza del tuo commento piuttosto scortese). Per favore, se ritieni di aver fatto qualcosa di irresponsabile qui che non avrei dovuto, quindi approfondisci ulteriormente - spiega perché . Non mi interessa molto il dibattito supponente che non ha sostanza.
rasoio

1
Il mio ultimo commento lo spiega perfettamente. Tutta la tua risposta potrebbe essere meglio scritta come while read f; do mkdir -p "$(dirname "$f")"; touch "$f"; done < files.txt. Anche il fatto che non si possa fare una ricerca su Internet di 10 secondi per UUOC lo dice
Steven Penny
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.