mkdir -p pour les fichiers

24

mkdir -pva créer un répertoire; il crée également des répertoires parents selon les besoins.

Existe-t-il une commande similaire pour les fichiers, qui créera un fichier et des répertoires parents selon les besoins?

Steven Penny
la source
Pas que je sache ... mais vous pouvez simplement faire mkdir -p / path / to / make && touch / path / to / file ... Ce qui ferait un fichier vide dans cette nouvelle structure de répertoires que vous avez créée selon vos besoins.
1
@Kansha combine cela avec dirnameet basenameet nous n'aurons besoin que d'un seul argument; profit! :)
Oui, bon appel.

Réponses:

29

L'installation le fera, si le fichier source lui est fourni /dev/null. L' -Dargument dit de créer tous les répertoires parents:

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

Je ne sais pas si c'est un bogue ou non - son comportement avec les fichiers de périphérique n'est pas mentionné dans la page de manuel. Vous pouvez également lui donner un fichier vierge (nouvellement créé avec mktemp, par exemple) comme source.

derobert
la source
7

Non, pas autant que je sache. Mais vous pouvez toujours utiliser mkdir -pet touchaprès l'autre:

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

J'ai souvent rencontré ce genre de situation, j'ai donc simplement écrit une fonction dans mon .bashrcfichier. Ça ressemble à ça

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
}

Donc, quand je veux créer un fichier dans un chemin de répertoires inexistants, je dirai

create what/is/it  # will create dirs 'what' and 'is', with file 'it' inside 'is'
ViKiG
la source
1
Mon homme! - merci, je l'ai appelé touchp, commemkdir -p
ecoologic
0
dir=$(dirname "$f")
test -d $dir || mkdir -p "$dir"
Yordan Georgiev
la source
3
Le testn'est pas nécessaire; mkdir -pne fait rien si le répertoire existe déjà. Ne renvoie même pas d'erreur.
derobert
1
Et bien sûr, cela ne fait que créer le répertoire.
un CVn du
0

J'allais suggérer car il la maintient sur une seule ligne, bien que définir la variable séparément vous permette de la changer et de réexécuter la commande à partir de l'historique assez facilement.

B="./make/this/path" && mkdir -p -- "$B" && touch -- "$B/file.txt"
Gilles 'SO- arrête d'être méchant'
la source
0

Il est possible de "truquer".

Tout d'abord, une théorie requise:

Rob Griffiths a publié un article en 2007 intitulé Facilement créer beaucoup de nouveaux dossiers sur Macworld.com dans lequel il a expliqué comment utiliser la xargscommande pour lire une liste de fichiers pour créer des répertoires mkdir.

xargsest capable de référencer a placeholder( {}) avec l' -Iindicateur, qui contient la valeur de chaque argument passé à xargs. Voici la différence entre avec ce drapeau et sans:

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

xargsest également capable d'exécuter des commandes shell arbitraires avec le sh -cdrapeau:

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

Combiner les concepts:

Nous pouvons combiner ces concepts avec mkdir -pau lieu de mkdiret le concept dans la réponse de @ldx pour produire ceci:

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

Cette commande mappe essentiellement chaque nom de fichier dans une liste de fichiers séparés par des lignes, coupe la partie de fichier, crée les répertoires avec mkdir -ppuis touches le nom de fichier dans son répertoire respectif.

Voici une ventilation de ce qui se passe dans la commande ci-dessus:

Dites par exemple mon files.txtapparence comme ceci:

deeply/nested/foo/bar.txt
deeply/nested/baz/fiz.txt
  • cat files.txt produit deeply/nested/foo/bar.js deeply/nested/baz/fiz.txt
  • deeply/nested/foo/bar.js deeply/nested/baz/fiz.txt est canalisé vers xargs
  • parce que nous avons utilisé -I {}, xargstraduira chaque argument dans sa propre commande, nous avons donc maintenant:
    • deeply/nested/foo/bar.txt
    • deeply/nested/baz/fiz.txt
  • nous exécutons ensuite une commande shell qui utilise le &&combinateur pour regrouper 3 commandes qui s'exécutent de manière séquentielle - la première commande stocke le fichier dans une variable d'environnement (qui est réutilisée lors de la prochaine passe de fichier) en utilisant l'espace réservé que nous avons enregistré auparavant, nous allons donc maintenant avoir:
    • f=deeply/nested/foo/bar.txt
    • f=deeply/nested/baz/fiz.txt
  • nous avons maintenant une variable à laquelle nous pouvons passer mkdir -p, mais nous devons couper le nom du fichier. Assez simple en utilisant '${f%/*}':
    • mkdir -p deeply/nested/foo/
    • mkdir -p deeply/nested/baz/
  • puis nous re-référençons simplement la fvariable dans son intégralité lorsque nous touch:
    • touch deeply/nested/foo/bar.txt
    • touch deeply/nested/baz/fiz.txt
rasoir
la source
2
Vous avez toute cette explication pour ce qui est essentiellement cat files.txt | xargs -I {} sh -c 'f="{}" && mkdir -p -- "${f%/*}" && touch -- "$f"', qui a UUOC, puis vous sous-shell en xargs qui sous-shell dans le shell, quand une while readboucle a plus de sens
Steven Penny
1
J'admets que je ne suis pas le plus informé des commandes * nix - je ne sais même pas ce qu'est UUOC - mais je ne vois pas comment c'est une réponse horrible. Il est recherché, testé et est une solution de travail à votre question d'origine. C'est constructif (contrairement à votre commentaire plutôt grossier). S'il vous plaît, si vous sentez que j'ai fait quelque chose d'irresponsable ici que je n'aurais pas dû, alors expliquez davantage - expliquez pourquoi . Peu m'importe le débat d'opinion qui n'a pas de substance.
razorbeard
1
Mon dernier commentaire l'explique parfaitement. Votre réponse entière pourrait être mieux écrite comme while read f; do mkdir -p "$(dirname "$f")"; touch "$f"; done < files.txt. Le fait que vous ne pouvez pas faire une recherche Internet de 10 secondes pour UUOC est également révélateur
Steven Penny