Bagaimana cara mengganti folder yang namanya adalah tanggal yaitu YYYYMMDD dengan hierarki folder tahun, bulan, tanggal?

8

Saya memiliki daftar folder yang memiliki tanggal untuk nama. Tanggal dalam format YYYYMMDD (mis. 20150129). Di dalam folder-folder ini terdapat dokumen teks yang terkait dengan tanggal tertentu.

Saya ingin merestrukturisasi mereka dalam hierarki folder dari tahun ke bulan hingga saat ini, dan untuk memindahkan dokumen teks ke folder 'tanggal' yang sesuai lebih rendah dalam hierarki.

Dengan kata lain saya ingin folder 'root' dinamai setelah tahun seperti 2015, dan kemudian membuat sub-folder bernama dengan bulan seperti 01, dan kemudian membuat sub-folder lebih lanjut bernama dengan tanggal seperti 29 yang menyimpan dokumen teks yang sesuai .

Jadi jalan akan terlihat seperti 2015/01/29/file.txtatau 2015>01>29>file.txt.

Saya telah melihat Automator dan sepertinya sesuatu seperti ini tidak mungkin walaupun saya mungkin salah, jadi saya ingin tahu ...

  1. Apakah ada solusi mudah untuk masalah ini yang dapat dipahami oleh orang awam, misalnya alur kerja Automator, atau apakah ini memerlukan pemahaman tentang perintah terminal dan ekspresi reguler?

  2. Bagaimana orang memecahkan masalah ini asalkan ada solusi?

davidjnatarajan
sumber
Kepada siapa pun yang memilih untuk menutup pertanyaan ini sebagai "terlalu luas", mengapa? Saya ingin tahu apa yang "terlalu luas" tentang pertanyaan ini?
user3439894
Apakah folder YYYYMMDD ini semua langsung berada di dalam satu folder master atau tersebar di hierarki yang lebih luas?
nohillside
@ patrix Dalam kasus saya mereka semua berada di direktori atau folder master yang sama
davidjnatarajan

Jawaban:

8

Dengan asumsi semua folder YYYYMMDD ini adalah bagian dari direktori induk yang sama yang dapat Anda jalankan

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
  • The for d in */; doLoop membaca semua entri direktori, trailing /memastikan bahwa hanya nama direktori benar-benar sesuai
  • [[ $d =~ [0-9]{8}/ ]] menguji apakah entri saat ini terdiri dari 8 digit, dan berlanjut dengan entri berikutnya jika tidak
  • ${d:0:4}/${d:4:2}/${d:6:2}menggunakan ekspansi parameter di dalam bashuntuk membuat string yang berisi jalur baru
  • Dalam --keduanya mkdirdan mvmencegah masalah jika direktori atau nama file dimulai dengan a -. Ini tidak bisa terjadi di sini, tapi mungkin itu praktik yang baik.

Terima kasih kepada @terdon dan @ user3439894 untuk ide tentang cara meningkatkan skrip asli.

nohillside
sumber
Terima kasih atas jawabannya, ini bekerja dengan sempurna! Saya merasa solusi ini lebih baik daripada yang disediakan oleh @grgarside karena jauh lebih cepat, terutama ketika berhadapan dengan corpus besar termasuk ribuan dokumen teks.
davidjnatarajan
8

Anda dapat menggunakan yang berikut ini di Terminal. cdke folder yang berisi, kemudian jalankan yang berikut:

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 fmemperoleh setiap file di direktori saat ini secara rekursif.
-exec bash -cmembuka shell untuk menjalankan perintah berikut.
F=$(…)membuka subkulit dan menggunakan sed pada path file untuk memanipulasi path ke dalam folder.
^\./([0-9]{4})([0-9]{2})([0-9]{2})adalah regex dengan tiga kelompok tangkap, sebagai berikut: adalah pengganti, di mana setiap kelompok tangkap ( , dll) dipisahkan oleh . membuat direktori untuk memindahkan file ke. memindahkan setiap file ke folder terkait.
\1/\2/\3\1/
mkdir -p -- $(dirname "$F")
mv -- "$1" "$F"

Ini mengambil hierarki di sebelah kiri dan mengubahnya menjadi hierarki di sebelah kanan:

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

Jika ada file lain di folder yang berisi dengan tanggal sebagai nama, mereka akan dipindahkan seolah-olah mereka adalah folder. Untuk mencegah hal ini, ganti baris kedua dengan:

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

The (?:/.+)memastikan bahwa path memiliki komponen berikutnya, karena itu mengabaikan apa pun tanpa anak di direktori induk yang merupakan file.

GRG
sumber
@klanomath regex101.com
GRG
@grgarside Thanx
klanomath