¿Cómo creo directorios nombrados después de cada mes?

8

Me gustaría crear un nombre de directorio para cada mes. Sé, después de jugar un poco con el caparazón, que:

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

Así que utilicé la expansión de llaves echo {1..12}/01y lo intenté xargs:

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

Pero falla miserablemente: / (luego me gustaría aplicar mkdir). ¿Cómo puedo hacer esto?

JammingThebBits
fuente
44
Parece que estás sobreprogramando esto. Si hay una razón, sería útil que explicaras por qué no escribes simplemente 12 líneas, "mkdir" Jan "; mkdir" Feb "; ...". Si necesita hacerlo varias veces, coloque el código en una función y llame según sea necesario.
jamesqf
44
¿Por qué nombra sus directorios con los nombres de los meses en lugar de los números 01-12? Tiene que ser incómodo tenerlos lsen orden alfabético (abril, agosto, diciembre, febrero, enero, julio, junio, marzo, mayo, noviembre, octubre, septiembre).
user1024
2
@jamesqf ¿Por qué harías eso cuando simplemente puedes hacerlo mkdir january february [...]? A menos que realmente necesite crearlos por separado, no es necesario hacerlo de la manera que sugirió.
Pryftan
@ user1024 Normalmente estaría de acuerdo con usted, pero tengo para un caso de uso el nombre de los meses (en minúsculas); en otro tengo 01 de enero, etc. ¿Quién puede decir? Existen numerosas razones por las que podría o podría ser mejor de una forma u otra. (Pero sí, si la clasificación es un problema ...)
Pryftan
@Pryftan: solo una preferencia personal para líneas más cortas :-) Además, si luego quisiera cambiar a, por ejemplo, "01Jan", es más fácil en mi editor hacer un "c / / 01/12 1" que hacer el cambio en una línea.
jamesqf

Respuestas:

17

Con -I, xargsobtiene un argumento por línea en lugar del valor predeterminado de un argumento por palabra (en blanco o nueva línea delimitada, posiblemente citada) sin -I(e implica -n). Entonces, en su ejemplo, datese llama solo una vez con {}expandido a toda la salida de echo(que está en una línea), menos la nueva línea final.

Aquí puede hacer (tenga en cuenta que -des una extensión de GNU):

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

(tenga en cuenta que no funcionará correctamente en entornos locales donde las abreviaturas de los nombres de los meses contienen espacios o comillas; con GNU xargs, puede solucionarlo utilizando xargs -d '\n' mkdir --)

Ahora, para obtener la lista de abreviaturas de mes en su localidad, consultar la localidad directamente tendría más sentido:

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

(vea también locale -k LC_TIMEpara ver todos los datos locales en la LC_TIMEcategoría).

O de forma nativa en zsh:

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

Al menos en los sistemas GNU, en algunas configuraciones regionales, las abreviaturas de los meses se rellenan con un ancho fijo con espacios:

$ 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

Es posible que desee eliminar ese relleno.

Los espacios iniciales se eliminarían xargs -I, pero no los espacios finales. Con zsh:

zmodload zsh/langinfo
set -o extendedglob
mkdir -- ${${${(v)langinfo[(I)ABMON*]}##[[:space:]]#}%%[[:space:]]#}
Stéphane Chazelas
fuente
¡Agradable! No sabía sobre locale abmon.
maulinglawns
Respuesta agradable, pero tl; dr: IFS=';'; set -o noglob; mkdir -- $(locale abmon). ;)
Skippy le Grand Gourou
9

Prueba un bucle?

$ 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 desea hacer un directorio para cada mes, haría algo como:

for m in {1..12}; do newdir=$(date -d "$m"/01 +%b); mkdir "$newdir"; done
maulinglawns
fuente
Tenga en cuenta que {1..12}es un bashismo. Para un shell POSIX, use for m in $(seq 1 12)...(aunque tenga en cuenta que seqPOSIX en sí mismo no es obligatorio)
Radovan Garabík
2
@ RadovanGarabík, técnicamente, {1..12}es un zshismo, copiado más tarde por ksh93, bash y varios otros proyectiles.
Stéphane Chazelas
5

En los shells con expansión de llaves y la fecha que acepta la entrada DATAFILE, intente

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

y la tubería en la cáscara si está satisfecho con el resultado.

RudiC
fuente
5

Su comando no funciona, debido al uso de -Icambios el delimitador de xargs:

-I replace-str
Reemplaza las ocurrencias de replace-str en los argumentos iniciales con nombres leídos de la entrada estándar. Además, los espacios en blanco sin comillas no terminan los elementos de entrada; en cambio, el separador es el carácter de nueva línea.

Puede agregar -d " "a xargs para que funcione. Pero ni siquiera necesitas -I{}en tu caso:

Prueba esto,

echo {1..12}/01 | xargs -n1 date +%b -d | xargs mkdir
pLumo
fuente
1
Tenga en cuenta que para que GNU dateacepte opciones después de argumentos no opcionales como ese, no debe haber una POSIXLY_CORRECTvariable en el entorno.
Stéphane Chazelas
3

Estás tan cerca.

El problema es que echo está produciendo una sola línea 1/01 2/01 3/01 4/01 5/01 6/01 7/01 8/01 9/01 10/01 11/01 12/01, y que xargs está usando el carácter de nueva línea como un separador de campo (no el espacio).

La solución: dile a echo que ponga un espacio entre cada campo.

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

Solo inserte \\nal final del eco.

Luego para hacer que los directorios agreguen |xargs mkdir

p.ej

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

ctrl-alt-delor
fuente
1

La forma más simple y robusta de hacer esto:

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

Es una lista estática de meses después de todo ...

Si tiene la intención de usar GNU date(aquí suponiendo un $IFSGNU no modificado y datesimilar para su date -d):

mkdir $( printf '%s\n' {1..12}/01 | date -f - +%b )
Kusalananda
fuente
2
Excepto que no hace abreviaciones de nombre de mes en el idioma del usuario.
Stéphane Chazelas
@ StéphaneChazelas A menos que sean suecos, como yo :-)
Kusalananda