Comment créer des répertoires nommés chaque mois?


8

Je voudrais créer un nom de répertoire pour chaque mois. Je sais, après avoir joué avec la coque, que:

date -d 1/01 +%b # Gives Jan
date -d 2/01 +%b # Gives Feb
.
date -d 12/01 +%b # Gives Dec

J'ai donc utilisé l'expansion d'accolade, echo {1..12}/01et j'ai essayé xargs:

echo {1..12}/01 | xargs -n 1 -I {} date -d {} +%b

Mais cela échoue lamentablement: / (après j'aimerais postuler mkdir). Comment puis-je faire ceci?


4
Vous semblez sur-programmer cela. S'il y a une raison, il serait utile que vous expliquiez pourquoi vous n'écrivez pas simplement 12 lignes, "mkdir" Jan "; mkdir" Feb "; ...". Si vous devez le faire plusieurs fois, mettez le code dans une fonction et appelez si nécessaire.
jamesqf

4
Pourquoi nommez- vous vos répertoires avec les noms des mois au lieu des numéros 01-12? Il doit être gênant de les lséditer par ordre alphabétique (avril, août, décembre, février, janvier, juillet, juin, mars, mai, novembre, octobre, septembre).
user1024

2
@jamesqf Pourquoi feriez-vous cela quand vous pouvez simplement le faire mkdir january february [...]? Sauf si vous devez vraiment les créer séparément, il n'est pas nécessaire de le faire comme vous l'avez suggéré.
Pryftan

@ user1024 Je serais normalement d'accord avec vous mais j'ai pour un cas d'utilisation le nom des mois (en minuscules cependant); dans un autre j'ai 01janvier etc. Qui peut dire? Il y a de nombreuses raisons pour lesquelles cela pourrait ou pourrait être mieux d'une manière ou d'une autre. (Mais oui - si le tri est un problème ...)
Pryftan

@Pryftan: Seulement une préférence personnelle pour des lignes plus courtes :-) De plus, si je voulais plus tard changer par exemple "01Jan", il est plus facile dans mon éditeur de faire un "c / / 01/12 1" que de faire le changement sur une ligne.
jamesqf

Réponses:


17

Avec -I, xargsobtient un argument par ligne par opposition à la valeur par défaut d'un argument par mot (vide ou délimité par une nouvelle ligne, éventuellement cité) sans -I(et implique -n). Ainsi, dans votre exemple, dateest appelé une seule fois avec {}étendu à la sortie entière de echo(qui se trouve sur une seule ligne), moins la nouvelle ligne de fin.

Ici, vous pouvez le faire (notez qu'il -ds'agit d'une extension GNU):

printf '%s\n' {1..12}/01 | xargs -I {} date -d {} +%b | xargs mkdir --

(notez que cela ne fonctionnera pas correctement dans les environnements locaux où les abréviations de nom de mois contiennent des espaces ou des guillemets; avec GNU xargs, vous pouvez contourner cela en utilisant xargs -d '\n' mkdir --)

Maintenant, pour obtenir la liste des abréviations de mois dans vos paramètres régionaux, interroger directement les paramètres régionaux aurait plus de sens:

(IFS=';'; set -o noglob; mkdir -- $(locale abmon))

(voir aussi locale -k LC_TIMEpour voir toutes les données locales dans la LC_TIMEcatégorie).

Ou nativement dans zsh:

zmodload zsh/langinfo
mkdir -- ${(v)langinfo[(I)ABMON_*]}

Au moins sur les systèmes GNU, dans certaines régions, les abréviations des mois sont complétées à une largeur fixe avec des espaces:

$ LC_ALL=et_EE.UTF-8 locale title abmon
Estonian locale for Estonia
jaan ;veebr;märts;apr  ;mai  ;juuni;juuli;aug  ;sept ;okt  ;nov  ;dets
$ LC_ALL=zh_TW.UTF-8 locale title abmon
Chinese locale for Taiwan R.O.C.
 1月; 2月; 3月; 4月; 5月; 6月; 7月; 8月; 9月;10月;11月;12

Vous souhaiterez peut-être supprimer ce rembourrage.

Les espaces en tête seraient supprimés par xargs -I, mais pas ceux en queue. Avec zsh:

zmodload zsh/langinfo
set -o extendedglob
mkdir -- ${${${(v)langinfo[(I)ABMON*]}##[[:space:]]#}%%[[:space:]]#}

Agréable! Ne savait pas locale abmon.
maulinglawns

Belle réponse, mais tl; dr: IFS=';'; set -o noglob; mkdir -- $(locale abmon). ;)
Skippy le Grand Gourou

9

Essayez une boucle?

$ for m in {1..12}; do
> date -d "$m"/01 +%b
> done
jan
feb
mar
apr
maj
jun
jul
aug
sep
okt
nov
dec

Si vous voulez faire un annuaire pour chaque mois, je ferais quelque chose comme:

for m in {1..12}; do newdir=$(date -d "$m"/01 +%b); mkdir "$newdir"; done

Notez que {1..12}c'est un bashisme. Pour un shell POSIX, utilisez for m in $(seq 1 12)...(mais notez que seqlui - même n'est pas mandaté par POSIX)
Radovan Garabík

2
@ RadovanGarabík, techniquement, {1..12}est un zshisme, copié plus tard par ksh93, bash et plusieurs autres obus.
Stéphane Chazelas

5

Dans les shells avec extension d'accolade et date acceptant l'entrée DATAFILE, essayez

echo {01..12}/01$'\n' | date -f- +"mkdir %b"

et canalisez dans la coquille si vous êtes satisfait du résultat.


5

Votre commande ne fonctionne pas, en raison de l'utilisation de -Imodifications du délimiteur de xargs:

-I replace-str
Remplace les occurrences de replace-str dans les arguments initiaux par des noms lus à partir de l'entrée standard. De plus, les espaces non entre guillemets ne terminent pas les éléments d'entrée; à la place, le séparateur est le caractère de nouvelle ligne.

Vous pouvez ajouter -d " "à xargs pour le faire fonctionner. Mais vous n'avez même pas besoin -I{}dans votre cas:

Essaye ça,

echo {1..12}/01 | xargs -n1 date +%b -d | xargs mkdir

1
Notez que pour que GNU dateaccepte des options après des arguments sans option comme ça, il ne doit pas y avoir de POSIXLY_CORRECTvariable dans l'environnement.
Stéphane Chazelas

3

Vous étiez si proche.

Le problème est que l'écho produit une seule ligne 1/01 2/01 3/01 4/01 5/01 6/01 7/01 8/01 9/01 10/01 11/01 12/01et que xargs utilise le caractère de nouvelle ligne comme séparateur de champ (pas l'espace).

La solution: dites à écho de mettre un espace entre chaque champ.

echo -e {1..12}/01\\n | xargs -n 1 -I {} date -d {} +%b

Je n'ai inséré \\nqu'à la fin de l'écho.

Ensuite, pour ajouter les répertoires |xargs mkdir

par exemple

echo -e {1..12}/01\\n | xargs -n 1 -I {} date -d {} +%b | xargs mkdir


1

La façon la plus simple et la plus robuste de le faire:

mkdir jan feb mar apr maj jun jul aug sep okt nov dec

C'est une liste statique de mois après tout ...

Si vous avez l'intention d'utiliser GNU date(en supposant ici un $IFSGNU non modifié et datesimilaire au vôtre date -d):

mkdir $( printf '%s\n' {1..12}/01 | date -f - +%b )

2
Sauf qu'il ne fait pas d'abréviations de nom de mois dans la langue de l'utilisateur.
Stéphane Chazelas

@ StéphaneChazelas A moins qu'ils ne soient suédois, comme moi :-)
Kusalananda
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.