Как мне создать каталоги, названные в честь каждого месяца?

8

Я хотел бы создать имя каталога для каждого месяца. Я знаю, после некоторой игры с оболочкой, что:

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

Поэтому я использовал расширение скобки echo {1..12}/01и попытался xargs:

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

Но это с треском проваливается: / (потом я хотел бы подать заявку mkdir). Как я могу это сделать?

JammingThebBits
источник
4
Вы, кажется, перепрограммируете это. Если есть причина, было бы полезно, если бы вы объяснили, почему вы просто не пишете 12 строк: "mkdir" Jan "; mkdir" Feb "; ...". Если вам нужно сделать это несколько раз, поместите код в функцию и при необходимости вызовите.
jamesqf
4
Почему вы называете свои каталоги названиями месяцев вместо цифр 01-12? Должно быть неудобно иметь их lsв алфавитном порядке (апр, август, декабрь, февраль, январь, июль, июнь, мар, май, ноябрь, октябрь, сентябрь).
user1024
2
@jamesqf Зачем тебе это делать, когда ты можешь просто сделать mkdir january february [...]? Если вам действительно не нужно создавать их отдельно, нет необходимости делать это так, как вы предлагали.
Прифтан
@ user1024 Я бы обычно согласился с вами, но у меня есть для одного варианта использования название месяца (хотя и в нижнем регистре); в другом у меня 01январь и т. д. Кто подскажет? Есть множество причин, по которым так или иначе может быть лучше. (Но да - если сортировка - это проблема ...)
Pryftan
@Pryftan: только личные предпочтения для более коротких строк :-) Кроме того, если я позже захочу изменить, например, на "01Jan", в моем редакторе легче сделать "c / / 01/12 1", чем сделать изменение на одна линия.
jamesqf

Ответы:

17

С -I, xargsполучает по одному аргументу на строку, в отличие от значения по умолчанию одного аргумента на слово -I( без пробелов или с новой строкой, возможно, в кавычках) без (и подразумевается -n) Таким образом, в вашем примере dateвызывается только один раз с {}расширением на весь вывод echo(который находится на одной строке), минус завершающий перевод строки.

Здесь вы можете сделать (обратите внимание, что -dэто расширение GNU):

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

(обратите внимание, что он не будет работать правильно в локалях, где сокращения названий месяцев содержат пробелы или символы кавычек; с GNU xargsвы можете обойти это, используя xargs -d '\n' mkdir --)

Теперь, чтобы получить список аббревиатур месяца в вашей локали, непосредственный запрос локали имеет смысл:

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

(см. также, locale -k LC_TIMEчтобы увидеть все данные локали в LC_TIMEкатегории).

Или изначально в zsh:

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

По крайней мере, в системах GNU, в некоторых регионах аббревиатуры месяцев дополняются до фиксированной ширины пробелами:

$ 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

Вы можете удалить это дополнение.

Ведущие места будут удалены xargs -I, но не последними. С zsh:

zmodload zsh/langinfo
set -o extendedglob
mkdir -- ${${${(v)langinfo[(I)ABMON*]}##[[:space:]]#}%%[[:space:]]#}
Стефан Шазелас
источник
Ницца! Не знал о locale abmon.
maulinglawns
Хороший ответ, но Т.Л., д - р: IFS=';'; set -o noglob; mkdir -- $(locale abmon). ;)
Скиппи ле Гран Гуру
9

Попробуйте петлю?

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

Если вы хотите сделать каталог для каждого месяца, я бы сделал что-то вроде:

for m in {1..12}; do newdir=$(date -d "$m"/01 +%b); mkdir "$newdir"; done
maulinglawns
источник
Обратите внимание, что {1..12}это башизм. Для оболочки POSIX используйте for m in $(seq 1 12)...(хотя обратите внимание, что seqсама POSIX не является обязательной)
Радован Гарабик
2
@ RadovanGarabík, технически, {1..12}это zshism, скопированный позже ksh93, bash и несколькими другими оболочками.
Стефан Шазелас
5

В оболочках с расширением скобок и датой, принимающей ввод данных, попробуйте

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

и труба в раковину, если доволен результатом.

Рудик
источник
5

Ваша команда не работает, из-за использования -Iизменений разделитель xargs:

-I replace-str
Заменить вхождения replace-str в исходных аргументах именами, считанными из стандартного ввода. Кроме того, пробелы без кавычек не заканчивают элементы ввода; вместо этого разделителем является символ перевода строки.

Вы можете добавить -d " "в xargs, чтобы он работал. Но вам даже не нужно -I{}в вашем случае:

Попробуй это,

echo {1..12}/01 | xargs -n1 date +%b -d | xargs mkdir
pLumo
источник
1
Обратите внимание, что для того, чтобы GNU dateмог принимать параметры после не аргументов, подобных этому, POSIXLY_CORRECTв среде не должно быть переменной.
Стефан Шазелас
3

Ты где так близко.

Проблема в том, что echo создает одну строку 1/01 2/01 3/01 4/01 5/01 6/01 7/01 8/01 9/01 10/01 11/01 12/01, а xargs использует символ новой строки в качестве разделителя полей (а не пробел).

Решение: Скажите эхо, чтобы поставить пробел между каждым полем.

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

Я вставил только \\nв конце эха.

Затем сделать каталоги добавить |xargs mkdir

например

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

Ctrl-Alt-Делор
источник
1

Самый простой и надежный способ сделать это:

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

В конце концов, это статичный список месяцев ...

Если вы намереваетесь использовать GNU date(здесь предполагается, что неизменным $IFSи GNU, dateкак для вашего date -d):

mkdir $( printf '%s\n' {1..12}/01 | date -f - +%b )
Кусалананда
источник
2
За исключением того, что это не делает сокращения названия месяца на языке пользователя.
Стефан Шазелас
@ StéphaneChazelas Если они не
шведы