Làm cách nào để tạo thư mục được đặt tên sau mỗi tháng?


8

Tôi muốn tạo một tên thư mục cho mỗi tháng. Tôi biết, sau khi chơi với cái vỏ, rằng:

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

Vì vậy, tôi đã sử dụng mở rộng cú đúp, echo {1..12}/01và đã thử xargsnó:

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

Nhưng nó thất bại thảm hại: / (sau đó tôi muốn áp dụng mkdir). Tôi có thể làm cái này như thế nào?


4
Bạn dường như đang lập trình quá mức này. Nếu có lý do, sẽ có ích nếu bạn giải thích lý do tại sao bạn không chỉ đơn giản viết 12 dòng, "mkdir" Jan "; mkdir" Feb "; ...". Nếu bạn cần làm điều đó nhiều lần, hãy đặt mã vào một hàm và gọi nếu cần.
jamesqf

4
Tại sao bạn đặt tên thư mục của bạn với tên của tháng thay vì số 01-12? Thật khó xử khi chúng được lssắp xếp theo thứ tự bảng chữ cái (tháng 4, tháng 8, tháng 12, tháng 2, tháng 1, tháng 7, tháng 6, tháng 3, tháng 5, tháng 11, tháng 10, tháng 9).
dùng1024

2
@jamesqf Tại sao bạn lại làm vậy khi bạn có thể làm mkdir january february [...]? Trừ khi bạn thực sự cần phải tạo chúng một cách riêng biệt, không cần phải làm theo cách bạn đề xuất.
Pryftan

@ user1024 Tôi thường đồng ý với bạn nhưng tôi có một trường hợp sử dụng tên của tháng (mặc dù là chữ thường); trong một cái khác tôi có 01 số tháng, v.v ... Ai có thể nói? Có nhiều lý do nó có thể hoặc có thể tốt hơn bằng cách này hay cách khác. (Nhưng có - nếu sắp xếp là một vấn đề ...)
Pryftan

@Pryftan: Chỉ một sở thích cá nhân cho các dòng ngắn hơn :-) Ngoài ra, nếu sau này tôi muốn thay đổi thành "01Jan", trình soạn thảo của tôi sẽ thực hiện "c / / 01/12 1" dễ dàng hơn so với thay đổi trên một đường thẳng.
jamesqf

Câu trả lời:


17

Với -I, xargsnhận được một đối số trên mỗi dòng trái ngược với mặc định của một đối số cho mỗi từ (phân cách trống hoặc dòng mới, có thể được trích dẫn) mà không có -I(và ngụ ý -n). Vì vậy, trong ví dụ của bạn datechỉ được gọi một lần với {}mở rộng ra toàn bộ đầu ra của echo(nằm trên một dòng), trừ đi dòng mới.

Ở đây bạn có thể làm (lưu ý rằng đó -dlà một phần mở rộng GNU):

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

(lưu ý rằng nó sẽ không hoạt động chính xác ở các địa phương nơi các chữ viết tắt tên tháng chứa khoảng trắng hoặc ký tự trích dẫn; với GNU xargs, bạn có thể xử lý xung quanh bằng cách sử dụng xargs -d '\n' mkdir --)

Bây giờ, để có được danh sách các chữ viết tắt tháng trong ngôn ngữ của bạn, truy vấn trực tiếp miền địa phương sẽ có ý nghĩa hơn:

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

(xem thêm locale -k LC_TIMEđể xem tất cả dữ liệu miền địa phương trong LC_TIMEdanh mục).

Hoặc nguyên bản trong zsh:

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

Ít nhất là trên các hệ thống GNU, ở một số địa phương, các chữ viết tắt tháng được đệm theo chiều rộng cố định với khoảng trắng:

$ 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

Bạn có thể muốn loại bỏ phần đệm đó.

Các không gian hàng đầu sẽ được loại bỏ xargs -I, nhưng không phải là không gian. Với zsh:

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

Đẹp! Không biết về locale abmon.
malawlawns

Câu trả lời hay, nhưng tl; dr : IFS=';'; set -o noglob; mkdir -- $(locale abmon). ;)
Skippy le Grand Gourou

9

Hãy thử một vòng lặp?

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

Nếu bạn muốn tạo một thư mục cho mỗi tháng, tôi sẽ làm một cái gì đó như:

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

Lưu ý rằng đó {1..12}là một bashism. Đối với vỏ POSIX, hãy sử dụng for m in $(seq 1 12)...(mặc dù lưu ý rằng seqbản thân nó không bắt buộc bởi POSIX)
Radovan Garabík

2
@ RadovanGarabík, về mặt kỹ thuật, {1..12}là một zshism, được sao chép sau bởi ksh93, bash và một số shell khác.
Stéphane Chazelas

5

Trong hệ vỏ có mở rộng dấu ngoặc và ngày chấp nhận đầu vào DATAFILE, hãy thử

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

và ống vào vỏ nếu hài lòng với kết quả.


5

Lệnh của bạn không hoạt động, vì sử dụng -Ithay đổi dấu phân cách của xargs:

-I thay thế-str
Thay thế các lần xuất hiện của thay thế trong các đối số ban đầu với các tên được đọc từ đầu vào tiêu chuẩn. Ngoài ra, khoảng trống không được trích dẫn không chấm dứt các mục đầu vào; thay vào đó dấu phân cách là ký tự dòng mới.

Bạn có thể thêm -d " "vào xargs để làm cho nó hoạt động. Nhưng bạn thậm chí không cần -I{}trong trường hợp của bạn:

Thử cái này,

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

1
Lưu ý rằng để GNU datechấp nhận các tùy chọn sau các đối số không phải tùy chọn như vậy, không được có một POSIXLY_CORRECTbiến trong môi trường.
Stéphane Chazelas

3

Bạn ở đâu rất gần.

Vấn đề là echo đang tạo ra một dòng duy nhất 1/01 2/01 3/01 4/01 5/01 6/01 7/01 8/01 9/01 10/01 11/01 12/01và xargs đang sử dụng ký tự dòng mới làm dấu tách trường (không phải khoảng trắng).

Giải pháp: Giới thiệu echo để đặt khoảng trắng giữa mỗi trường.

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

Tôi chỉ chèn \\nvào cuối tiếng vang.

Sau đó để làm cho các thư mục thêm |xargs mkdir

ví dụ

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


1

Cách đơn giản nhất và mạnh mẽ nhất để làm điều này:

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

Đó là một danh sách tĩnh của nhiều tháng sau tất cả ...

Nếu bạn có ý định sử dụng GNU date(ở đây giả sử một $IFSGNU chưa được sửa đổi và datenhư của bạn date -d):

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

2
Ngoại trừ việc nó không viết tắt tên tháng trong ngôn ngữ của người dùng.
Stéphane Chazelas

@ StéphaneChazelas Trừ khi họ là người Thụy Điển, như tôi :-)
Kusalananda
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.