Làm thế nào để thay thế một thư mục tên đó là một ngày tức là YYYYMMDD bằng hệ thống phân cấp thư mục của năm, tháng, ngày?


8

Tôi có một danh sách các thư mục có ngày tháng cho tên. Các ngày có định dạng YYYYMMDD (ví dụ 20150129). Trong các thư mục này là các tài liệu văn bản có liên quan đến ngày cụ thể đó.

Tôi muốn cơ cấu lại chúng trong hệ thống phân cấp thư mục từ năm này sang tháng khác và để di chuyển các tài liệu văn bản vào thư mục 'ngày' tương ứng thấp hơn trong hệ thống phân cấp.

Nói cách khác, tôi muốn thư mục 'root' được đặt tên theo năm như 2015, sau đó tạo các thư mục con có tên như tháng, và sau đó tạo thêm các thư mục con có tên như ngày 29 chứa các tài liệu văn bản tương ứng .

Vì vậy, con đường sẽ như thế nào 2015/01/29/file.txthoặc 2015>01>29>file.txt.

Tôi đã xem qua Automator và dường như điều gì đó như thế này là không thể mặc dù tôi có thể sai, vì vậy tôi muốn biết ...

  1. Có một số giải pháp dễ dàng cho vấn đề này mà bất kỳ giáo dân nào cũng có thể hiểu được, ví dụ như quy trình làm việc của Automator, hoặc điều này đòi hỏi một số hiểu biết về các lệnh đầu cuối và các biểu thức thông thường?

  2. Làm thế nào một người sẽ giải quyết vấn đề này với điều kiện là có một giải pháp?


Để bất cứ ai bỏ phiếu để đóng câu hỏi này là "quá rộng", tại sao? Tôi tò mò về những gì "quá rộng" về câu hỏi này?
dùng3439894

Đây có phải là tất cả các thư mục YYYYMMDD trực tiếp trong một thư mục chính hay chúng được trải rộng trên một hệ thống phân cấp rộng hơn?
nohillside

@patrix Trong trường hợp của tôi, tất cả chúng đều nằm trong cùng một thư mục hoặc thư mục chính
davidjnatarajan

Câu trả lời:


8

Giả sử tất cả các thư mục YYYYMMDD này là một phần của cùng thư mục mẹ bạn có thể chạy

cd PARENT_DIRECTORY
for d in */; do
    [[ $d =~ [0-9]{8}/ ]] || continue
    mkdir -p -- "${d:0:4}/${d:4:2}"
    mv -- "$d" "${d:0:4}/${d:4:2}/${d:6:2}"
done
  • Các for d in */; dovòng lặp đọc tất cả các mục thư mục, trailing /bảo đảm rằng chỉ tên thư mục thực sự phù hợp
  • [[ $d =~ [0-9]{8}/ ]] kiểm tra xem mục hiện tại có bao gồm 8 chữ số hay không và tiếp tục với mục tiếp theo nếu không
  • ${d:0:4}/${d:4:2}/${d:6:2}sử dụng mở rộng tham số bên trong bashđể tạo một chuỗi chứa đường dẫn mới
  • Cả --hai mkdirmvngăn chặn sự cố trong trường hợp tên thư mục hoặc tệp bắt đầu bằng a -. Điều này không thể xảy ra ở đây nhưng dù sao nó cũng có thể là thực hành tốt.

Cảm ơn @terdon và @ user3439894 về ý tưởng về cách cải thiện tập lệnh gốc.


Cảm ơn câu trả lời, điều này hoạt động hoàn hảo! Tôi cảm thấy giải pháp này tốt hơn giải pháp do @grgarside cung cấp vì nó nhanh hơn rất nhiều, đặc biệt là khi xử lý một khối lượng lớn bao gồm hàng ngàn tài liệu văn bản.
davidjnatarajan

8

Bạn có thể sử dụng như sau trong Terminal. cdvào thư mục chứa, sau đó chạy như sau:

find . -type f -exec bash -c \
  'F=$(sed -E "s#^\./([0-9]{4})([0-9]{2})([0-9]{2})#\1/\2/\3#" <<< $1);\
  mkdir -p -- $(dirname "$F");\
  mv -- "$1" "$F"' - {} \;

find . -type fcó được mọi tập tin trong thư mục hiện tại đệ quy.
-exec bash -cmở một shell để chạy các lệnh sau.
F=$(…)mở một lớp con và sử dụng sed trên đường dẫn tệp để thao tác đường dẫn vào các thư mục.
^\./([0-9]{4})([0-9]{2})([0-9]{2})là một regex với ba nhóm chụp, như sau: là sự thay thế, trong đó mỗi nhóm chụp ( , v.v.) được phân tách bằng . tạo các thư mục để di chuyển các tập tin vào. di chuyển từng tập tin vào thư mục tương ứng của nó.
\1/\2/\3\1/
mkdir -p -- $(dirname "$F")
mv -- "$1" "$F"

Cái này lấy thứ bậc ở bên trái và chuyển nó thành thứ bậc ở bên phải:

├── 20170201               └── 2017
   └── abcdefghij             ├── 02
└── 20170302                      └── 01
    └── abcdefghij 2                  └── abcdefghij
                               └── 03
                                   └── 02
                                       └── abcdefghij 2

Nếu có các tệp khác trong thư mục chứa ngày có tên, chúng sẽ được di chuyển như thể chúng là một thư mục. Để ngăn chặn điều này, thay thế dòng thứ hai bằng:

  'F=$(sed -E "s#^\./([0-9]{4})([0-9]{2})([0-9]{2})(?:/.+)#\1/\2/\3#" <<< $1);\

Việc (?:/.+)đảm bảo rằng đường dẫn có một thành phần tiếp theo, do đó bỏ qua mọi thứ mà không có con trong thư mục cha là các tệp.


@klanomath regex101.com
GRG

@grgarside Thanx
klanomath
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.