¿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?


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:]]#}

¡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

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.


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

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


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 )

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
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.