mkdir -p für Dateien

24

mkdir -perstellt ein Verzeichnis; Bei Bedarf werden auch übergeordnete Verzeichnisse erstellt.

Gibt es einen ähnlichen Befehl für Dateien, der nach Bedarf eine Datei und übergeordnete Verzeichnisse erstellt?

Steven Penny
quelle
Nicht, dass mir das bewusst wäre ... aber Sie könnten einfach mkdir -p / path / to / make && touch / path / to / file ... ausführen. Dadurch würde eine leere Datei in der neuen Verzeichnisstruktur erstellt, die Sie bei Bedarf erstellt haben.
1
@Kansha kombiniert das mit dirnameund basenameund wir brauchen nur das einzige Argument; profitieren! :)
Ja, guten Ruf.

Antworten:

29

Install wird dies tun, wenn die Quelldatei angegeben wird /dev/null. Das -DArgument besagt, dass alle übergeordneten Verzeichnisse erstellt werden sollen:

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

Nicht sicher, ob das ein Fehler ist oder nicht - sein Verhalten mit Gerätedateien wird in der Manpage nicht erwähnt. Sie können ihm auch einfach eine leere Datei ( mktempzum Beispiel neu erstellt mit ) als Quelle geben.

derobert
quelle
7

Nein, soweit ich weiß, ist es nicht so. Sie können aber immer mkdir -pund touchnacheinander verwenden:

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

Ich bin häufig auf solche Situationen gestoßen, deshalb habe ich einfach eine Funktion in meine .bashrcDatei geschrieben. Es sieht aus wie das

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
}

Wenn ich also eine Datei in einem Pfad nicht vorhandener Verzeichnisse erstellen möchte, werde ich sagen

create what/is/it  # will create dirs 'what' and 'is', with file 'it' inside 'is'
ViKiG
quelle
1
Mein Mann! - danke, ich nannte es touchp, wiemkdir -p
ecoologic
0
dir=$(dirname "$f")
test -d $dir || mkdir -p "$dir"
Jordan Georgiev
quelle
3
Das testwird nicht benötigt; mkdir -ptut nichts, wenn das Verzeichnis bereits existiert. Gibt nicht einmal einen Fehler zurück.
Derobert
1
Dabei wird natürlich nur das Verzeichnis erstellt.
einen Lebenslauf vom
0

Ich wollte vorschlagen, wie es es in einer Zeile hält, obwohl das separate Festlegen der Variablen es Ihnen ermöglicht, es zu ändern und den Befehl aus dem Verlauf ziemlich einfach erneut auszuführen.

B="./make/this/path" && mkdir -p -- "$B" && touch -- "$B/file.txt"
Gilles 'SO - hör auf böse zu sein'
quelle
0

Es ist möglich, es zu "fälschen".

Erstens einige erforderliche Theorie:

Rob Griffiths veröffentlichte 2007 einen Artikel mit dem Titel " Einfach viele neue Ordner erstellen" auf Macworld.com, in dem er die Verwendung des xargsBefehls zum Einlesen einer Liste von Dateien zum Erstellen von Verzeichnissen mit erläuterte mkdir.

xargskann auf ein placeholder( {}) mit dem -IFlag verweisen , das den Wert für jedes Argument enthält, an das übergeben wird xargs. Hier ist der Unterschied zwischen mit dieser Flagge und ohne:

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

xargskann auch beliebige Shell-Befehle mit dem sh -cFlag ausführen :

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

Die Konzepte kombinieren:

Wir können diese Konzepte mit und mkdir -panstelle des mkdirKonzepts in @ldx 's Antwort kombinieren , um Folgendes zu erzeugen:

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

Dieser Befehl ordnet grundsätzlich jeden Dateinamen in einer zeilengetrennten Liste von Dateien zu, schneidet den Dateiteil ab, erstellt die Verzeichnisse mit mkdir -pund es dann touchden Dateinamen in seinem jeweiligen Verzeichnis.

Hier ist eine Aufschlüsselung dessen, was im obigen Befehl passiert:

Sagen Sie zum Beispiel, dass mein files.txtAussehen so ist:

deeply/nested/foo/bar.txt
deeply/nested/baz/fiz.txt
  • cat files.txt produziert deeply/nested/foo/bar.js deeply/nested/baz/fiz.txt
  • deeply/nested/foo/bar.js deeply/nested/baz/fiz.txt wird zu geleitet xargs
  • da wir verwendet haben -I {}, xargswird jedes Argument in einen eigenen Befehl übersetzt, so dass wir jetzt haben:
    • deeply/nested/foo/bar.txt
    • deeply/nested/baz/fiz.txt
  • Anschließend führen wir einen Shell-Befehl aus, der den &&Kombinator verwendet, um 3 Befehle zu gruppieren, die nacheinander ausgeführt werden. Der erste Befehl speichert die Datei in einer Umgebungsvariablen (die beim nächsten Dateidurchlauf wiederverwendet wird) und verwendet dabei den zuvor registrierten Platzhalter haben:
    • f=deeply/nested/foo/bar.txt
    • f=deeply/nested/baz/fiz.txt
  • Wir haben jetzt eine Variable, an die wir übergeben können mkdir -p, aber wir müssen den Dateinamen ausschneiden. Einfach genug mit '${f%/*}':
    • mkdir -p deeply/nested/foo/
    • mkdir -p deeply/nested/baz/
  • und dann referenzieren wir die fVariable einfach in ihrer Gesamtheit neu, wenn wir touch:
    • touch deeply/nested/foo/bar.txt
    • touch deeply/nested/baz/fiz.txt
Rasierbart
quelle
2
Sie haben all diese Erklärungen für das Wesentliche cat files.txt | xargs -I {} sh -c 'f="{}" && mkdir -p -- "${f%/*}" && touch -- "$f"', was UUOC hat, dann unterteilen Sie in Xargs, die wieder in die Shell unterteilen, wenn eine while readSchleife sinnvoller ist
Steven Penny
1
Ich gebe zu, dass ich keine Ahnung von * nix-Befehlen habe - ich weiß nicht einmal, was UUOC ist -, aber ich verstehe nicht, wie schrecklich diese Antwort ist. Es wurde recherchiert, getestet und ist eine funktionierende Lösung für Ihre ursprüngliche Frage. Es ist konstruktiv (im Gegensatz zu Ihrem eher unhöflichen Kommentar). Bitte, wenn Sie das Gefühl haben, dass ich hier etwas Verantwortungsloses getan habe, das ich nicht hätte tun sollen, dann gehen Sie weiter vor - erklären Sie, warum . Meinungsverschiedene Debatten, die keine Substanz haben, interessieren mich nicht sonderlich.
Razorbeard
1
Mein letzter Kommentar erklärt es perfekt. Ihre gesamte Antwort könnte besser geschrieben werden als while read f; do mkdir -p "$(dirname "$f")"; touch "$f"; done < files.txt. Die Tatsache, dass Sie keine 10-Sekunden-Internetsuche nach UUOC durchführen können, ist ebenfalls bezeichnend
Steven Penny