Come posso creare directory che prendono il nome da ogni mese?


8

Vorrei creare un nome di directory per ogni mese. So, dopo aver giocato con la shell, che:

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

Quindi ho usato l'espansione del controvento echo {1..12}/01e ho provato a xargsfarlo:

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

Ma fallisce miseramente: / (dopo vorrei applicare mkdir). Come posso fare questo?


4
Sembra che tu stia programmando troppo. Se c'è una ragione, sarebbe utile se spiegassi perché non scrivi semplicemente 12 righe, "mkdir" Jan "; mkdir" Feb "; ...". Se è necessario farlo più volte, inserire il codice in una funzione e chiamare come necessario.
jamesqf

4
Perché stai nominando le tue directory con i nomi dei mesi anziché i numeri 01-12? Deve essere imbarazzante vederli lsin ordine alfabetico (aprile, agosto, dicembre, febbraio, gennaio, luglio, giugno, marzo, maggio, novembre, ottobre, settembre).
user1024

2
@jamesqf Perché dovresti farlo quando puoi semplicemente farlo mkdir january february [...]? A meno che non sia necessario crearli separatamente, non è necessario farlo nel modo suggerito.
Pryftan,

@ user1024 Normalmente sono d'accordo con te ma ho per un caso d'uso il nome dei mesi (minuscole però); in un altro ho 01 gennaio, ecc. Chi può dirlo? Ci sono numerose ragioni per cui potrebbe o potrebbe essere meglio in un modo o nell'altro. (Ma sì, se l'ordinamento è un problema ...)
Pryftan,

@Pryftan: solo una preferenza personale per le linee più brevi :-) Inoltre, se in seguito volessi cambiare ad esempio "01Jan", nel mio editor è più facile fare un "c / / 01/12 1" piuttosto che fare il cambio su una linea.
jamesqf,

Risposte:


17

Con -I, xargsottiene un argomento per riga anziché il valore predefinito di un argomento per parola (vuota o delimitata da una nuova riga, eventualmente citata) senza -I(e implica -n). Quindi nel tuo esempio dateviene chiamato solo una volta con {}espanso all'intero output di echo(che è su una riga), meno la nuova riga finale.

Qui puoi fare (nota che si -dtratta di un'estensione GNU):

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

(nota che non funzionerà correttamente in locali in cui le abbreviazioni dei nomi dei mesi contengono spazi o virgolette; con GNU xargs, puoi aggirare ciò usando xargs -d '\n' mkdir --)

Ora, per ottenere l'elenco delle abbreviazioni dei mesi nelle impostazioni locali, eseguire una query direttamente sulle impostazioni locali avrebbe più senso:

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

(vedi anche locale -k LC_TIMEper vedere tutti i dati di localizzazione nella LC_TIMEcategoria).

O nativamente in zsh:

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

Almeno sui sistemi GNU, in alcune versioni locali, le abbreviazioni dei mesi sono riempite a larghezza fissa con spazi:

$ 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

Potresti voler rimuovere quell'imbottitura.

Gli spazi iniziali verrebbero rimossi xargs -I, ma non quelli finali. Con zsh:

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

Bello! Non lo sapevo locale abmon.
Maulinglawns

Bella risposta, ma tl; dr: IFS=';'; set -o noglob; mkdir -- $(locale abmon). ;)
Skippy le Grand Gourou l'

9

Prova un loop?

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

Se vuoi creare una directory per ogni mese, farei qualcosa del tipo:

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

Si noti che {1..12}è un basismo. Per una shell POSIX, utilizzare for m in $(seq 1 12)...(sebbene si noti che seqnon è obbligatorio per POSIX)
Radovan Garabík

2
@ RadovanGarabík, tecnicamente, {1..12}è uno zshism, copiato in seguito da ksh93, bash e molte altre shell.
Stéphane Chazelas,

5

Nelle shell con espansione di parentesi graffe e data che accetta l'input DATAFILE, provare

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

e pipe in shell se soddisfatto del risultato.


5

Il tuo comando non funziona, a causa dell'uso -Icambia il delimitatore di xargs:

-I replace-str
Sostituisce le occorrenze di replace-str negli argomenti iniziali con nomi letti dall'input standard. Inoltre, gli spazi vuoti non quotati non terminano gli elementi di input; invece il separatore è il carattere di nuova riga.

Puoi aggiungerlo -d " "a xargs per farlo funzionare. Ma non hai nemmeno bisogno -I{}nel tuo caso:

Prova questo,

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

1
Nota che affinché GNU dateaccetti le opzioni dopo argomenti non opzionali come quello, non deve esserci una POSIXLY_CORRECTvariabile nell'ambiente.
Stéphane Chazelas,

3

Sei stato così vicino.

Il problema è che l'eco sta producendo una sola riga 1/01 2/01 3/01 4/01 5/01 6/01 7/01 8/01 9/01 10/01 11/01 12/01e che xargs sta usando il carattere newline come separatore di campo (non lo spazio).

La soluzione: dire all'eco di inserire uno spazio tra ciascun campo.

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

Ho inserito solo \\nalla fine dell'eco.

Quindi per aggiungere le directory |xargs mkdir

per esempio

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


1

Il modo più semplice e robusto per farlo:

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

È un elenco statico di mesi dopo tutto ...

Se hai intenzione di usare GNU date(qui assumendo un $IFSGNU non modificato e datecome per il tuo date -d):

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

2
Tranne che non contiene abbreviazioni dei nomi dei mesi nella lingua dell'utente.
Stéphane Chazelas,

@ StéphaneChazelas A meno che non siano svedesi, come me :-)
Kusalananda
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.