如何创建每个月命名的目录?


8

我想为每个月创建一个目录名称。我知道,在玩了一些shell之后,我知道:

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)。我怎样才能做到这一点?


4
您似乎对此编程过度。如果有原因,请解释一下为什么不简单地写12行“ mkdir“ Jan”; mkdir“ Feb”; ...“。如果需要多次执行,请将代码放入函数中,然后根据需要调用。
jamesqf

4
为什么用目录名称而不是数字01-12 命名目录?让他们ls按字母顺序进行编辑会很尴尬(4月,8月,12月,2月,1月,7月,6月,3月,5月,11月,10月)。
user1024

2
@jamesqf为什么您可以简单地这样做mkdir january february [...]呢?除非您确实需要单独创建它们,否则无需按照建议的方式进行操作。
Pryftan

@ user1024我通常会同意您的意见,但是在一个用例中,我有月份的名称(不过是小写);在另一个我有01january等。谁能告诉?有多种原因可能会或可能会更好。(但是的-如果排序是一个问题...)
Pryftan

@Pryftan:个人更喜欢短行:-)另外,如果以后我要更改为“ 01Jan”,则在我的编辑器中执行“ c / / 01/12 1”要比进行更改更容易。一条线。
jamesqf

Answers:


17

使用时-Ixargs每行获取一个自变量,而不是每个不带-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

尼斯的答案,但TL;博士:IFS=';'; set -o noglob; mkdir -- $(locale abmon)。;)
Skippy le Grand Gourou

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

注意这{1..12}是一种bashism。对于POSIX外壳,请使用for m in $(seq 1 12)...(尽管请注意,seq它本身不是POSIX强制要求的)
RadovanGarabík18年

2
@RadovanGarabík从技术上讲{1..12}是zshism,后来被ksh93,bash和其他一些shell复制。
斯特凡Chazelas

5

在具有大括号扩展名且日期接受DATAFILE输入的shell中,请尝试

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

1
请注意,要让GNU date接受像这样的非选项参数之后的选项,POSIXLY_CORRECT环境中不得有 变量。
斯特凡Chazelas

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在每个字段之间放置一个空格。

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


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
除非它不会使用用户的语言来表示月份名称的缩写。
斯特凡Chazelas

@StéphaneChazelas除非他们像我一样是瑞典人:-)
Kusalananda
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.