Wie erstelle ich Verzeichnisse, die nach jedem Monat benannt sind?

8

Ich möchte für jeden Monat einen Verzeichnisnamen erstellen. Ich weiß nach einigem Spielen mit der Muschel, dass:

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

Also habe ich die Klammererweiterung verwendet echo {1..12}/01und versucht xargs:

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

Aber es scheitert kläglich: / (danach möchte ich mich bewerben mkdir). Wie kann ich das machen?

JammingThebBits
quelle
4
Sie scheinen dies zu überprogrammieren. Wenn es einen Grund gibt, wäre es hilfreich, wenn Sie erklären würden, warum Sie nicht einfach 12 Zeilen schreiben: "mkdir" Jan "; mkdir" Feb "; ...". Wenn Sie dies mehrmals tun müssen, fügen Sie den Code in eine Funktion ein und rufen Sie ihn nach Bedarf auf.
Jamesqf
4
Warum benennen Sie Ihre Verzeichnisse mit den Namen der Monate anstelle der Nummern 01-12? Es muss unangenehm sein, sie lsin alphabetischer Reihenfolge zu bearbeiten (April, August, Dezember, Februar, Januar, Juli, Juni, März, Mai, November, Oktober, September).
user1024
2
@jamesqf Warum würdest du das tun, wenn du es einfach kannst mkdir january february [...]? Sofern Sie sie nicht wirklich separat erstellen müssen, müssen Sie sie nicht so ausführen, wie Sie es vorgeschlagen haben.
Pryftan
@ user1024 Normalerweise stimme ich Ihnen zu, aber ich habe für einen Anwendungsfall den Namen der Monate (allerdings in Kleinbuchstaben). in einem anderen habe ich 01january etc. Wer kann das sagen? Es gibt zahlreiche Gründe, warum es auf die eine oder andere Weise besser oder besser sein könnte. (Aber ja - wenn das Sortieren ein Problem ist ...)
Pryftan
@Pryftan: Nur eine persönliche Präferenz für kürzere Zeilen :-) Auch wenn ich später zu zB "01Jan" wechseln wollte, ist es in meinem Editor einfacher, ein "c / / 01/12 1" durchzuführen, als die Änderung vorzunehmen eine Linie.
Jamesqf

Antworten:

17

Mit -I, xargswird ein Argument pro Zeile auf die Standardeinstellung von einem Argumente im Gegensatz pro (leer oder Newline begrenzt, möglicherweise zitiert) Wort ohne -I(und impliziert -n). In Ihrem Beispiel datewird also nur einmal aufgerufen {}, wobei die gesamte Ausgabe von echo(die sich in einer Zeile befindet) abzüglich der nachfolgenden neuen Zeile erweitert wird.

Hier können Sie Folgendes tun (beachten Sie, dass dies -deine GNU-Erweiterung ist):

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

(Beachten Sie, dass dies in Gebietsschemas, in denen Abkürzungen für Monatsnamen Leerzeichen oder Anführungszeichen enthalten, nicht ordnungsgemäß funktioniert. Mit GNU xargskönnen Sie dies mithilfe von umgehen. xargs -d '\n' mkdir --)

Um die Liste der Monatsabkürzungen in Ihrem Gebietsschema zu erhalten, ist es sinnvoller, das Gebietsschema direkt abzufragen:

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

(Siehe auch locale -k LC_TIME, um alle Gebietsschemadaten in der LC_TIMEKategorie anzuzeigen ).

Oder nativ in zsh:

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

Zumindest auf GNU-Systemen werden in einigen Regionen die Monatsabkürzungen mit Leerzeichen auf eine feste Breite aufgefüllt:

$ 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

Möglicherweise möchten Sie diese Polsterung entfernen.

Die führenden Leerzeichen würden von entfernt xargs -I, aber nicht die nachfolgenden. Mit zsh:

zmodload zsh/langinfo
set -o extendedglob
mkdir -- ${${${(v)langinfo[(I)ABMON*]}##[[:space:]]#}%%[[:space:]]#}
Stéphane Chazelas
quelle
Nett! Wusste nichts davon locale abmon.
Maulinglawns
Schöne Antwort, aber tl; dr : IFS=';'; set -o noglob; mkdir -- $(locale abmon). ;)
Skippy le Grand Gourou
9

Versuchen Sie eine Schleife?

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

Wenn Sie für jeden Monat ein Verzeichnis erstellen möchten, würde ich Folgendes tun:

for m in {1..12}; do newdir=$(date -d "$m"/01 +%b); mkdir "$newdir"; done
maulinglawns
quelle
Beachten Sie, dass dies {1..12}ein Bashismus ist. Verwenden Sie für eine POSIX-Shell for m in $(seq 1 12)...(obwohl beachten Sie, dass seqselbst nicht von POSIX vorgeschrieben)
Radovan Garabík
2
@ RadovanGarabík ist technisch gesehen {1..12}ein Zshismus, der später von ksh93, bash und mehreren anderen Shells kopiert wird.
Stéphane Chazelas
5

Versuchen Sie es in Shells mit Klammererweiterung und Datum, an dem die Eingabe von DATAFILE akzeptiert wird

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

und in die Schale leiten, wenn Sie mit dem Ergebnis zufrieden sind.

RudiC
quelle
5

Ihr Befehl funktioniert nicht, da -Idas Trennzeichen von xargs geändert wird:

-I replace-str
Ersetzt das Auftreten von replace-str in den Anfangsargumenten durch Namen, die aus der Standardeingabe gelesen wurden. Auch unquoted Rohlingen führen nicht zum Abbruch Eingabeelemente; Stattdessen ist das Trennzeichen das Zeilenumbruchzeichen.

Sie können -d " "xargs hinzufügen , damit es funktioniert. Aber Sie brauchen -I{}in Ihrem Fall nicht einmal :

Versuche dies,

echo {1..12}/01 | xargs -n1 date +%b -d | xargs mkdir
pLumo
quelle
1
Beachten Sie, dass es für GNU datekeine POSIXLY_CORRECTVariable in der Umgebung geben darf, damit Optionen nach solchen Nicht-Optionsargumenten akzeptiert werden .
Stéphane Chazelas
3

Du warst so nah dran.

Das Problem ist, dass Echo eine einzelne Zeile erzeugt 1/01 2/01 3/01 4/01 5/01 6/01 7/01 8/01 9/01 10/01 11/01 12/01und dass xargs das Zeilenumbruchzeichen als Feldtrennzeichen verwendet (nicht das Leerzeichen).

Die Lösung: Sagen Sie echo, dass zwischen jedem Feld ein Leerzeichen stehen soll.

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

Ich habe nur \\nam Ende des Echos eingefügt .

Dann, um die Verzeichnisse hinzuzufügen |xargs mkdir

z.B

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

Strg-Alt-Delor
quelle
1

Der einfachste und robusteste Weg, dies zu tun:

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

Es ist doch eine statische Liste von Monaten ...

Wenn Sie beabsichtigen, GNU zu verwenden date(hier unter der Annahme einer unveränderten $IFSund GNU- dateähnlichen für Sie date -d):

mkdir $( printf '%s\n' {1..12}/01 | date -f - +%b )
Kusalananda
quelle
2
Es werden jedoch keine Monatsnamenabkürzungen in der Sprache des Benutzers vorgenommen.
Stéphane Chazelas
@ StéphaneChazelas Es sei denn, sie sind schwedisch, wie ich :-)
Kusalananda